stderr по ssh-t

Как в другом ответе говорится, это могло бы быть зеркало, не абсолютно актуально, или возможно обновления были выставлены частично. Можно попробовать yum clean metadata (который сдувает yumидея доступных пакетов, и т.д., но не, что это уже загрузило), и попробовали еще раз, добавляя --skip-broken (который опускает пакеты, которые не могут быть обновлены по любой причине). Возможно, Вам нужны несколько раундов выполнения этого. Посмотрите на пакет, на который это жалуется, попробовать yum reinstall это. Рассмотрите выполнение package-cleanup (от yum-utils пакет), это помогает в фиксации большого количества несоответствий.

11
03.06.2014, 02:41
2 ответа

Я не думаю, что вы сможете обойти это.

С -tt, sshd порождает псевдотерминал и делает ведомую часть stdin, stdout и stderr оболочки, выполняющей удаленную команду.

sshd читает то, что поступает с его (единственного) fd на ведущую часть псевдотерминала и отправляет это (по одному единственному каналу) клиенту ssh. Второго канала для stderr нет, как и без -t.

Кроме того, обратите внимание, что дисциплина терминальной строки псевдотерминала может (и будет по умолчанию) изменять вывод. Например, LF будет преобразована в CRLF там, а не на локальном терминале, поэтому вы можете захотеть отключить постобработку вывода.

$ ssh  localhost 'echo x' | hd
00000000  78 0a                                             |x.|
00000002
$ ssh -t localhost 'echo x' | hd
00000000  78 0d 0a                                          |x..|
00000003
$ ssh -t localhost 'stty -opost; echo x' | hd
00000000  78 0a                                             |x.|
00000002

Многое другое будет происходить на стороне ввода (например, символ ^C, который вызовет SIGINT, а также другие сигналы, эхо и вся обработка, связанная с каноническим режимом строкового редактора).

Вы можете перенаправить stderr в fifo и получить его с помощью второго ssh:

ssh -tt host 'mkfifo fifo && cmd 2> fifo' &
ssh host 'cat fifo' >&2

Но лучше всего, IMO, вообще не использовать -t. Это действительно предназначено только для интерактивного использования с реального терминала.

Вместо того, чтобы полагаться на передачу ^C, чтобы сообщить удаленному концу, что соединение закрыто, можно использовать обертку, которая делает poll(), чтобы обнаружить убитый ssh или закрытое соединение.

Возможно, что-то вроде (упрощенно, вы захотите добавить некоторую проверку ошибок):

LC_HUP_DETECTOR='
  use IO::Poll;
  $SIG{CHLD} = sub {$done = 1};
  $p = IO::Poll->new;
  $p->mask(STDOUT, POLLIN);
  $pid=fork; unless($pid) {setpgrp; exec @ARGV; die "exec: $!\n"}
  $p->poll;
  kill SIGHUP, -$pid unless $done;
  wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8)
' ssh host 'perl -e "$LC_HUP_DETECTOR" some cmd'

Приведенная выше $p->mask(STDOUT, POLLIN) может показаться глупой, но идея заключается в том, чтобы ждать события зависания (закрытия читающего конца трубы на stdout). POLLHUP как запрошенная маска игнорируется. POLLHUP имеет смысл только как событие возврата (чтобы сообщить, что конец записи был закрыт).

Мы должны дать ненулевое значение для маски события. Если мы используем 0, perl даже не вызовет poll. Поэтому здесь мы используем POLLIN.

В Linux, что бы вы ни запросили, если труба становится разорванной, poll() возвращает POLLERR.

На Solaris и FreeBSD, где трубы двунаправленные, когда конец трубы для чтения (который там же является и концом для записи) закрывается, возвращается POLLHUP (и POLLIN на FreeBSD, где вы должны запросить POLLIN, иначе $p->poll() не возвращается).

Я не могу сказать, насколько она переносима за пределами этих трех операционных систем.

5
27.01.2020, 19:59

Чтобы заставить его работать на других платформах, это стало окончательным решением. Он проверяет, отключился ли клиент ssh и, таким образом, родительский идентификатор стал pid 1:

$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
    # Make own process group to be able to kill HUP it later
    setpgrp;
    exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV");
    die "exec: $!\n";
}
do {
    # Parent is not init (ppid=1), so sshd is alive
    # Exponential sleep up to 1 sec
    $s = $s < 1 ? 0.001 + $s * 1.03 : $s;
    select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)
1
27.01.2020, 19:59

Теги

Похожие вопросы