我有一个使用如下命令运行的 perl 脚本:
/path/to/binary/executable | /path/to/perl/script.pl
该脚本对二进制文件的输出执行有用的操作,然后在 STDIN 用完后退出( 返回 undef)。这一切都很好,除非二进制文件以非零代码退出。从脚本的 POV 来看,它认为脚本刚刚干净地结束,因此它清理并退出,代码为 0.
有没有办法让 perl 脚本查看退出代码是什么?理想情况下,我希望这样的事情能够工作:
# close STDIN, and if there was an error, exit with that same error.
unless (close STDIN) {
print "error closing STDIN: $! ($?)\n";
exit $?;
}
但不幸的是,这似乎不起作用:
$ (date; sleep 3; date; exit 1) | /path/to/perl/script.pl /tmp/test.out
Mon Jun 7 14:43:49 PDT 2010
Mon Jun 7 14:43:52 PDT 2010
$ echo $?
0
有没有办法让它按我的意思做?
编辑添加:
Perl 脚本实时操作二进制命令的输出,因此将其全部缓冲到文件中并不是一个可行的解决方案。但是,在脚本结束之前它不需要知道退出代码。
bash环境变量$PIPESTATUS
是一个数组,其中包含最后一个命令管道的每个部分的状态。例如:
$ false | true; echo "PIPESTATUS: ${PIPESTATUS[@]}; ?: $?"
PIPESTATUS: 1 0; ?: 0
所以听起来你不需要重构你的 perl 脚本,你只需要运行该管道命令的脚本来检查$PIPESTATUS
。使用$PIPESTATUS
没有[@]
给出数组第一个元素的值。
如果您需要检查初始可执行文件和 perl 脚本的状态,您需要首先将 $PIPESTATUS 分配给另一个变量:
status=(${PIPESTATUS[@]})
然后你可以单独检查它们,例如
if (( ${status[0]} )); then echo "main reactor core breach!"; exit 1;
elif (( ${status[1]} )); then echo "perls poisoned by toxic spill!"; exit 2;
fi;
您必须通过临时变量来执行此操作,因为下一条语句,即使它是一个if
声明,将重置${PIPESTATUS[@]}
在以下语句之前,即使它是一个elif
声明,可以查一下。
请注意,这个东西仅适用于 bash 而不是原始的 bourne shell(通常sh
,尽管许多系统链接/bin/sh
to /bin/bash
由于其向后兼容性)。因此,如果将其放入 shell 脚本中,第一行应该是
#!/bin/bash
而不是#!/bin/sh
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)