我正在编写一个Perl脚本,它应该在shell中执行命令并解析它们的输出。作为一个shell,我打算使用csh。我已经开始了这个
my $out = `cmd`
但它不捕获STDERR,我也需要它。使用输出重定向运行sh不会执行任何操作
my $out = `sh -c "cmd 2>&1"`
仍然只捕获STDOUT,而不是STDERR。
即使重定向到csh中的文件也不适合我
tcsh$ cmd >& logfile.log
仍然仅捕获STDOUT%)
我正在尝试执行的命令是actuallty sh脚本,此脚本中的一些命令打印到STDERR中,我想捕获该输出。如果我执行sh -c "cmd 2>/dev/null"
STDERR实际上转到/ dev / null并且只在终端中打印STDOUT。
有人可以帮我吗?
答案 0 :(得分:1)
在这里,您正在捕获sh
的STDOUT,它不是cmd
的STDERR:
my $out = `sh -c "cmd 2>&1"`;
您可以直接运行cmd
吗?
my $out = `cmd 2>&1`;
答案 1 :(得分:1)
system
会将stdout和stderr转储到其父级设置中。 IPC::Open3
这样的东西:与open2()非常相似,open3()会产生给定的$ cmd并连接CHLD_OUT以便从孩子那里读取,CHLD_IN用于写入孩子,CHLD_ERR用于错误。如果CHLD_ERR为假,
答案 2 :(得分:1)
我遇到过同样的问题。在进行了一些研究之后,我遇到了这篇文章:Capture stderr as well as stdout from a tcs。在这篇文章的最后,作者找到了他的解决方法,这也满足了我的要求。我想你可以试一试。它可以很好地合并stderr和stdout的输出。
答案 3 :(得分:1)
我相信有些事你没有告诉我们。你在cygwin吗?还是Windows?您是否设置了PERL5SHELL
环境变量?
有些事情你没有告诉我们,因为这些都可以在我可以轻松测试的五个平台上正常工作:
% perl -le '$out = `sh -c "grep missing /dev/nowhere 2>&1" | cat -n`; chomp $out; print "got <<<$out>>>"'
got <<< 1 grep: /dev/nowhere: No such file or directory>>>
但到目前为止,没有理由明确地将 sh (1)称为shelling out。那是因为Perl 总是调用 sh (1)来解决所有反引号,管道打开以及system()
炮轰:
% perl -le '$out = `grep missing /dev/nowhere 2>&1 | cat -n`; chomp $out; print "got <<<$out>>>"'
got <<< 1 grep: /dev/nowhere: No such file or directory>>>
我能想到的除此之外的唯一情况发生在非Unix系统上,因为它们没有 / bin / sh ,所以还定义了其他内容。
但在任何情况下,简单的炮轰都不会在背后召唤 tcsh (1)。您必须严重破解 perl (1)来源才能实现这一目标。我还怀疑你可以(轻松地)破解二进制文件,因为字符串"/bin/tcsh"
将比"/bin/sh"
更长,并且它通常不会在 / bin中找到/ 无论如何。
即使从shell开始,你也无法让stderr重定向工作,这说明了一些非常奇怪的事情。我想我们需要更多信息。
答案 4 :(得分:1)
你说在tcsh中运行命令cmd >& logfile.log
只会将cmd的stdout发送到日志文件,而不是stderr。这没有意义。
尝试使用以下脚本替换cmd:
#!/bin/sh
echo stdout
echo STDERR 1>&2
“stdout”和“STDERR”都应该出现在logfile.log中。
如果是这样,那么也许你的“cmd”正在做一些奇怪的事情。我最好的猜测是cmd写入/ dev / tty,而不是写入stdout或stderr;这不会受到重定向的影响。
要了解我的意思,请将此行添加到上述脚本中:
echo tty > /dev/tty
答案 5 :(得分:1)
我没有时间像往常一样模拟一个例子,甚至没有测试一个例子。我想你可以尝试使用Capture::Tiny
看看是否有帮助。