Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl';s backticks/系统给出“;tcsetattr:输入/输出错误“;_Perl_Ssh - Fatal编程技术网

Perl';s backticks/系统给出“;tcsetattr:输入/输出错误“;

Perl';s backticks/系统给出“;tcsetattr:输入/输出错误“;,perl,ssh,Perl,Ssh,我正在编写一个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])

我正在编写一个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
在server01上运行脚本
$tcsetattr:输入/输出错误
与server01的连接已关闭


使用
系统运行时也会出现相同的结果(因为我需要脚本的输出,所以最好使用反勾号)。当我在命令行的两个反勾号之间运行确切的命令时,它的工作方式与预期完全相同。是什么导致了这种情况?

这可能是因为当stdin/stdout不是真正的tty时,您强制SSH分配tty。SSH尝试调用这些处理程序上的某些特定tty函数(可能是从远程端转发的),但调用失败并返回一些错误

你有什么理由要分配tty吗


还有什么理由使用过时的SSH协议版本1吗?

当SSH试图将本地终端置于“原始”模式时,
tcsettr:Input/output error
消息来自SSH(这涉及到对tcsetattr的调用;请参见
sshtty.c
中的
enter_raw_mode
,从
clientloop.c
中的
client_loop
调用)

根据IEEE Std 1003.12004(Posix),如果调用进程位于孤立(或后台?)进程组中,则tcsetattr可能返回-1,并带有
errno==EIO
(即“输入/输出错误”)

实际上,ssh正在尝试更改本地终端的设置,即使它不在前台进程组中(由于您的fork和本地脚本正在退出(在您引用的输出中的错误消息之前出现了明显的shell提示)

如果您只是想避免错误消息,那么可以使用
ssh-ntt
(从/dev/null重定向stdin,但要求远程端无论如何分配一个tty),而不是
ssh-t
(当然,还可以添加
-l
和您需要的任何其他选项)


更可能的情况是,只要某些远程进程仍在运行,您就会对保持本地脚本运行感兴趣。为此,您需要使用函数(或其“亲戚”)等待每个分叉进程退出,然后再退出分叉它们的程序(只要启动它们的程序在前台进程组中,就可以将它们保留在前台进程组中)。不过,您可能仍然希望使用
-n
,因为如果您分叉的多个ssh实例都试图同时使用(从本地终端读取或更改本地终端的设置),这会造成混乱


作为一个简单的演示,您可以让本地脚本在分叉所有子进程后执行
sleep 30
,以便ssh命令在它们是前台进程组的一部分时有时间启动。这应该会抑制错误消息,但它不会实现您声明的目标。您需要
等待
(如果我正确解释了你的目标).

我认为这是一个ell,即登录选项,而不是一个。分配tty是因为如果没有tty,当此脚本被终止时,远程进程将继续运行。我需要在终止此脚本时终止它们,-t是我知道的唯一方法。我将在周一加入时尝试您的建议。等待:远程脚本将永远运行到当这个脚本被杀的时候,他们就被杀了,所以我不认为我需要等待他们。不过我必须调查。