【发布时间】:2014-12-01 05:52:02
【问题描述】:
请耐心等待,描述很长。
在 perl 中,我想执行一个简单的远程命令并使用 perl::Expect 捕获输出)。但是我发现我的结果数组有时是空的。我做了很多实验,相信问题是我的远程 ssh 连接在远程命令可以刷新到 stout 之前成功终止。
- 无论是直接从 bash 命令行运行 perl::Expect 还是 ssh,行为都是相同的。
- 我的数据中心的所有主机都有这种行为。主机负载越多,错误就越频繁。对于重型主机,我大约有 15% 的时间无法得到结果。在较轻的主机上,错误率接近 0。
- 远程命令无关紧要。
- 我知道我正在通过密码提示并进入远程主机。使用 'ssh -vvv' 我每次都会看到远程命令被执行。
- 我已经通过执行尾随虚拟命令并检查远程返回代码来进行实验,以期刷新标准输出缓冲区。没有什么是可靠的。
以下示例已编辑用户/组/主机名。除此之外,输出是未经编辑的剪切和粘贴。
> 虽然是真的;做回声“开始”; ssh -l 用户主机'日期; ls -l abc;回声$?';回声“结束”;完毕 开始 密码: 2014 年 10 月 6 日星期一 13:06:51 PDT -rw-r--r-- 1 个用户组 34538 2012 年 12 月 6 日 abc 0 结尾 开始 密码: 结尾 开始 密码: 2014 年 10 月 6 日星期一 13:06:54 PDT 结尾如果我将远程命令发送到一个虚拟文件,那么 stdout 也会被刷新,并且我每次都能可靠地从我的命令中获取输出。不幸的是,这是一个 hack 解决方法。
虽然是真的;做回声“开始”; ssh -l 用户主机'日期| tee -a /tmp/date.txt' ;回声“结束”;完毕不要纠结于这个例子中的 perl 细节。有趣的是返回的@output 数组。在 perl 我有以下命令:
local::rc::Utils::executeRemoteCommand( $cmd, $pass, 0, undef, undef, \@output )
最终深入到调用这个:
我的 $ssh = Expect->spawn($command);
生成的 $command 是这样的:
ssh -l 用户主机 "ls -l abc;echo 'DONE';echo $?"
“打印转储器\@output”成功:
$VAR1 = [
#0
" ",
#1
"-rw-r--r-- 1 user group 34538 Dec 6 2012 abc",
#2
"DONE",
#3
0
];
“打印转储器\@output”失败:
$VAR1 = [
#0
" ",
#1
"DONE",
#2
0
];
请注意“ls”的结果是如何未被捕获的,但“DONE”的回声却是。我还看到了输出数组在哪里有 ls 结果但没有回声。我还看到了两个结果都缺失的地方。
任何见解将不胜感激。在这一点上,我被难住了,现在必须将这些远程调用编程到一个循环中,以检查预期的结果。这是一个可怕的黑客攻击。我更愿意解决根本原因。
非常感谢
【问题讨论】:
-
"ssh -l user host "ls -l abc;echo "DONE";echo $?""在ls之前有什么特别的原因吗?有奇数个引号 -
另外,我会尝试保护
$?值不被当前值替代。所以我会尝试对 \\$?,\\\$?进行一些变体。祝你好运。 -
Travis - 已修复引号。这只是这篇文章中的一个错字。实际执行是正确的。所有三个命令都在远程端执行。
-
shellter - $?大多是无关紧要的。我只是试图强制远程命令读取远程返回代码,希望这会刷新标准输出。
-
我的同事还指出,shell 会话不刷新标准输出存在一个已知问题。如果是这样,我可以在远程命令上使用命令行参数来强制刷新输出缓冲区吗?