Обратные ссылки / система Perl дают "tcsetattr: Ошибка ввода / вывода" - PullRequest
3 голосов
/ 14 мая 2011

Я пишу Perl-скрипт, который запускает скрипт на нескольких разных серверах, используя ssh. Удаленный сценарий должен запускаться, пока выполняется этот сценарий:

#!/usr/bin/perl
require 'config.cfg'

#@servers is defined in config.cfg
#Contains server info as [username,hostname]
#
# @servers = ([username,server1.test.com],[username,server2.test.com]) 
#
foreach $server ( @servers ) {
    my $pid = fork();
    if ( $pid == 0 ) {
        $u = ${$server}[0];
        $h = ${$server}[1];
        print "Running script on $h \n";
        print `ssh -tl $u $h perl /opt/scripts/somescript.pl`;
        exit 0;
    } else {
        die "Couldn't start the process: $!\n";
    }
}
[...]

Когда я запускаю этот скрипт, я получаю следующий вывод:

. / Brokenscript.pl
Запуск сценария на сервере 01
$ tcsetattr: ошибка ввода / вывода
Соединение с сервером01 закрыто.

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

Ответы [ 2 ]

4 голосов
/ 14 мая 2011

Сообщение tcsetattr: Input/output error приходит от ssh , когда оно пытается перевести локальный терминал в «сырой» режим (который включает в себя вызов tcsetattr ; см. enter_raw_mode in sshtty.c, вызывается с client_loop в clientloop.c).

Из IEEE Std 1003.1, 2004 (Posix) Раздел 11.1.4: Контроль доступа к терминалу , tcsetattr может возвращать -1 с помощью errno == EIO (т.е. «Input /ошибка вывода »), если вызывающий процесс находится в потерянной (или фоновой?) группе процессов.

Эффективно ssh пытается изменить настройку локального терминала, даже если он не находится вгруппа процессов переднего плана (из-за вашего fork и выхода из локального сценария (о чем свидетельствует видимое приглашение оболочки, которое появляется непосредственно перед сообщением об ошибке в вашем цитируемом выводе)).

Есливы просто хотите избежать сообщения об ошибке, вы можете использовать ssh -ntt (перенаправить стандартный ввод из / dev / null, но в любом случае попросить удаленную сторону выделить tty) вместо ssh -t (добавьте -l и любые другие параметрыконечно, вам нужно вернуться обратно.


Скорее всего, вам интересно поддерживать работу локального сценария, пока некоторые из удаленных процессов все еще работают.Для этого вам нужно использовать функцию wait (или одного из его «родственников»), чтобы дождаться завершения каждого разветвленного процесса перед выходом из программы, которая разветвила их (это сохранит их вгруппа процессов переднего плана, пока в них есть программа, которая их запустила).Возможно, вы все равно захотите использовать -n, так как было бы странно, если бы несколько экземпляров ssh , которые вы разветвили, все пытались использовать (считывать или изменять настройки) локальный терминал нав то же время.

В качестве простой демонстрации вы можете сделать так, чтобы локальный скрипт выполнял sleep 30 после разветвления всех дочерних элементов, чтобы у команд ssh было время для запуска, покаони являются частью группы процессов переднего плана.Это должно подавить сообщение об ошибке, но оно не будет соответствовать вашей заявленной цели.Для этого вам нужно wait (если я правильно понимаю вашу цель).

0 голосов
/ 14 мая 2011

Это, вероятно, происходит потому, что вы заставляете SSH выделять tty, когда stdin / stdout на самом деле не ttys. SSH пытается вызвать определенную функцию tty в этих обработчиках (возможно, переадресованную с удаленной стороны), и вызов завершается неудачно, возвращая некоторую ошибку.

Есть ли причина, по которой вы должны выделять tty?

Есть ли какая-либо причина использовать устаревшую версию 1 протокола SSH?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...