例如,以下工作正常:
/usr/bin/program
它产生一些输出,并得到结果。
但如果我像这样调用它:
echo -n | /usr/bin/program
或这个
echo -n | bash -c "/usr/bin/program"
甚至这个:
echo -n | bash -c "wc -c; /usr/bin/program"
它产生一些输出行,然后失败。我无法访问该程序的源代码,因此我什至无法查看可能导致此行为的原因。
当我尝试从 python 脚本调用它时,我得到了同样的东西:
echo | python -c 'from subprocess import call; call("/usr/bin/program", shell=True)'
(没有“echo”前缀的版本工作正常)
我什至不知道为什么会发生这种情况。即使我没有明确指定程序应该从哪里读取,标准输入也会打开,所以这不应该是原因。
有什么办法可以解决这个问题吗?
编辑:
输出的最后四行strace
- 唯一不同的行:
# without echo
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
...
# with echo
select(1, [0], NULL, NULL, {0, 0}) = 1 (in [0], left {0, 0})
write(4, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
write(3, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
exit_group(1) = ?
部分解决方案:
sleep 20 | /usr/bin/program
似乎program
等待 stdin 发生某些事情,如果遇到换行符或 EOF 则退出(我们可以从select
strace 输出中的调用中看到它 - 如果输入来自“真实”用户,它就会超时)。因此,我们需要一个程序,它不会向标准输入写入任何内容,同时仍保持打开状态 -sleep
完成这项工作。
答案1
这是一个 Perl 单行代码,可以满足您的要求:
perl -e '$SIG{CHLD} = sub{exit 0}; open $fh, "|-", @ARGV or die; sleep 20 while 1;' /usr/bin/program
它本质上与神话*相同sleep forever | /usr/bin/program
,除了它还监视程序完成,并在完成时立即退出。如果 /usr/bin/program 需要任何参数,您可以将它们添加到该行的末尾。
*sleep forever
不起作用,但 GNU sleep 将永远休眠,如果你sleep inf
!