Perl 的反引号/系统给出“tcsetattr:输入/输出错误”

Posted

技术标签:

【中文标题】Perl 的反引号/系统给出“tcsetattr:输入/输出错误”【英文标题】:Perl's backticks/system giving "tcsetattr: Input/output error" 【发布时间】:2011-05-13 20:27:03 【问题描述】:

我正在编写一个 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 的连接已关闭。

使用system 运行时会出现相同的结果(无论如何,反引号是首选,因为我想要脚本的输出)。当我在命令行上的反引号之间运行确切的命令时,它完全按预期工作。这是什么原因造成的?

【问题讨论】:

【参考方案1】:

tcsetattr: Input/output error 消息来自 ssh,当它试图将本地终端置于“原始”模式时(这涉及到对 tcsetattr 的调用;参见 enter_raw_modesshtty.c 中,从client_loopclientloop.c 中调用)。

根据 IEEE Std 1003.1, 2004 (Posix) Section 11.1.4: Terminal Access Control,如果调用进程处于孤立 (还是背景?)进程组。

有效地 ssh 正在尝试更改本地终端的设置,即使它不在前台进程组中(由于您的 fork 并且本地脚本正在退出(正如您引用的输出中的错误消息之前的明显 shell 提示所证明的那样)。

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


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

作为一个简单的演示,您可以让本地脚本在分叉所有子节点后执行sleep 30,以便 ssh 命令有时间在它们属于前台进程组。这应该会抑制错误消息,但不会解决您的既定目标。为此,您需要 wait(如果我正确解释了您的目标)。

【讨论】:

我会在星期一进来的时候试试你的建议。等待:远程脚本永远运行,直到当这个脚本被杀死时它们被杀死,所以我认为我不需要等待它们。不过我得调查一下。【参考方案2】:

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

你有什么理由应该分配一个 tty 吗?

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

【讨论】:

我认为这是一个 ell,即登录选项,而不是一个。 分配一个 tty 因为没有它,当这个脚本被杀死时,远程进程继续运行。当这个人被杀死时,我需要他们被杀死,而 -t 是我知道的唯一方法。

以上是关于Perl 的反引号/系统给出“tcsetattr:输入/输出错误”的主要内容,如果未能解决你的问题,请参考以下文章

在perl的反引号中使用chmod后导致权限的异步更改的原因

perl 第五弹 变量 I

使用反引号在 perl 脚本中获取核心文件

mysql的反引号backtick

perl中的单引号和双引号

Perl和操作系统交互:systemexec和反引号