В настоящее время я запускаю mcabber как свой Jabber-клиент (который использует ncurses) в сеансе tmux на моем домашнем сервере. Локально я запускаю iTerm2 как эмулятор терминала, который поддерживает запуск уведомлений рычания через escape-последовательности символов.
Примечание: Все echo
в этом вопросе работает как printf %b
, или echo -e
в bash и GNU echo
.
например, echo "\e]9;foobar\007"
заставляет iTerm2 отправлять сообщение Growl с текстом «foobar».
Однако в сеансе tmux escape-последовательности съедаются. Поэтому использование фирменной escape-последовательности символов \Ptmux
может быть использовано следующим образом:
echo "\ePtmux;\e\e]9;foobar\007\e\\"
Это вызывает рычащее сообщение из сеанса tmux.
Однако когда я использую это в своем скрипте событий mcabber, который запускается при получении нового сообщения, уведомление не срабатывает, как будто эхо отправлено на неправильный терминал.
Полагаю, это связано с тем, что mcabber, который запускает скрипт, является приложением ncurses, поэтому вывод моего обычного скрипта bash теряется, и iTerm 2 никогда его не видит.
Я также пытался вызвать smcup, но безуспешно, прежде чем повторить некоторые идеи, которые я обнаружил
tput smcup
echo "\ePtmux;\e\e]9;$FROM: $MSG\007\e\\"
tput rmcup
Полагаю, это не сработает, поскольку проблема не в переключении обратно в «реальное окно терминала», а в направлении вывода в окно ncurses.
Есть идеи по этому поводу?
решение1
Причина, по которой сценарий события не может отправить сообщение «Growler», заключается в следующем:mcabber
закрывает стандартный ввод,выходи потоки ошибок, когда он запускает команду события. Вы можете увидеть это вhooks.c
:
if ((pid=fork()) == -1) {
scr_LogPrint(LPRINT_LOGNORM, "Fork error, cannot launch external command.");
g_free(datafname);
return;
}
if (pid == 0) { // child
// Close standard file descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
if (execl(extcmd, extcmd, arg_type, arg_info, bjid, arg_data,
(char *)NULL) == -1) {
// scr_LogPrint(LPRINT_LOGNORM, "Cannot execute external command.");
exit(1);
}
}
g_free(datafname);
Это позволяет скрипту события работать, не мешая потокам, используемымmcabber
.
Специального режима ncurses, перехватывающего сообщение, не существует (в конце концов tmux
,ужезапущенный как приложение terminfo). Вероятно, вы можете обойти эту проблему, перенаправив свой echo
(предпочтительно printf
) на /dev/tty
, например,
#!/bin/sh
printf '\033Ptmux;\033\033]9;foobar\007\033\\' >/dev/tty
решение2
Программы tmux и screen напрямую не проходят через escape-последовательности. Они представляют один тип терминала приложению (тип терминала screen) и сами являются приложением ncurses для другого терминала. По сути, это что-то вроде транслятора терминала. Так что да, он потребляет (или отбрасывает) последовательности для типа терминала «screen» и выставляет буфер, который вы видите. Затем он берет эти события изменения буфера и использует любой тип терминала, который вы используете в данный момент, для отображения текущего буфера. Таким образом, исходное приложение и терминал просмотра разделены.
решение3
Если бы вы написали что-то вроде...
export "PTTY=$(tty)"
...в вашем /etc/profile
тогда для каждой новой -l
оболочки ogin, которую вы вызовете(что обычно и происходит, когда вы открываете новое окно терминала)эта переменная среды будет доступна всем ее дочерним процессам, в том числе tmux
и всем ее дочерним процессам.
Это должно позволить вам сделать...
printf '\033]9;foobar\007' >"$PTTY"
...и тем самым пропустить все pty
слои, которые могут существовать между вашей текущей оболочкой и используемым вами эмулятором терминала.
решение4
Если проблема заключается в том, что выходные данные вашего bash-скрипта теряются, то вы можете выиграть битву с помощью перенаправления:
echo "\ePtmux;\e\e]9;foobar\007\e\" > /dev/tty
Однако я подозреваю, что настоящая проблема заключается в том, что вам следует использовать echo -e
команду , чтобы bash обрабатывал escape-последовательности в вашей строке.