Perl 的反引号/系统给出“tcsetattr:输入/输出错误"; [英] Perl's backticks/system giving "tcsetattr: Input/output error"

查看:71
本文介绍了Perl 的反引号/系统给出“tcsetattr:输入/输出错误";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 perl 脚本,它使用 ssh 在几个不同的服务器上启动一个脚本.只要这个脚本在运行,远程脚本就需要运行:

I'm writing a perl script that kicks off a script on several different servers using ssh. The remote script needs to run as long as this script is running:

#!/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";
    }
}
[...]

当我运行这个脚本时,我得到以下输出:

When I run this script, I get the following output:

./brokenscript.pl
在 server01 上运行脚本
$ tcsetattr:输入/输出错误
与 server01 的连接已关闭.

./brokenscript.pl
Running script on server01
$ tcsetattr: Input/output error
Connection to server01 closed.

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

The same result occurs when running with system (and backticks are preferred anyways since I want the output of the script). When I run the exact command between the backticks on the command line, it works exactly as expected. What is causing this?

推荐答案

tcsetattr: Input/output error 消息来自 ssh 当它尝试放置本地终端时进入原始"模式(包括调用 tcsetattr;参见 sshtty.c 中的 enter_raw_mode,从 client_loop 调用> 在 clientloop.c 中).

The tcsetattr: Input/output error message comes from ssh when it tries to put the local terminal into "raw" mode (which involves a call to tcsetattr; see enter_raw_mode in sshtty.c, called from client_loop in clientloop.c).

来自 IEEE Std 1003.1, 2004 (Posix) 第 11.1 节.终端访问控制tcsetattr 可能会返回-1 和errno == EIO(即输入/输出错误"),如果调用进程处于孤立状态(或背景?)进程组.

From IEEE Std 1003.1, 2004 (Posix) Section 11.1.4: Terminal Access Control, tcsetattr may return -1 with errno == EIO (i.e. "Input/output error") if the calling process is in an orphaned (or background?) process group.

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

Effectively ssh is trying to change the setting of the local terminal even though it is not in the foreground process group (due of your fork and, the local script exiting (as evidenced by the apparent shell prompt that comes immediately before the error message in your quoted output)).

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

If you just want to avoid the error message, you can use ssh -ntt (redirect stdin from /dev/null, but ask the remote side to allocate a tty anyway) instead of ssh -t (add your -l and any other options you need back in too, of course).

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

More likely, you are interesting in keeping the local script running as long as some of the remote processes are still running. For that, you need to use the wait function (or one of its "relatives") to wait for each forked process to exit before you exit the program that forked them (this will keep them in the foreground process group as long as the program that started them is in it). You may still want to use -n though, since it would be confusing if the multiple instances of ssh that you forked all tried to use (read from, or change the settings of) the local terminal at the same time.

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

As a simple demonstration, you could have the local script do sleep 30 after forking off all the children so that the ssh command(s) have time to start up while they are part of the foreground process group. This should suppress the error message, but it will not address your stated goal. You need wait for that (If I am interpreting your goal correctly).

这篇关于Perl 的反引号/系统给出“tcsetattr:输入/输出错误";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆