gpt4 book ai didi

Perl 的反引号/系统给出 "tcsetattr: Input/output error"

转载 作者:行者123 更新时间:2023-12-05 00:40:51 31 4
gpt4 key购买 nike

我正在编写一个 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
Running script on server01
$ tcsetattr: Input/output error
Connection to server01 closed.



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

最佳答案

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

来自 IEEE Std 1003.1, 2004 (Posix) Section 11.1.4: Terminal Access Control , tcsetattr 可能会用 errno == EIO 返回 -1 (即“输入/输出错误”)如果调用进程在孤立(或后台?)进程组中。

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

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

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

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

关于Perl 的反引号/系统给出 "tcsetattr: Input/output error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5997387/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com