这个问题已经在这里有一个答案:
- 如何检查的第一个程序的状态在管道中的Perl的系统()? 7个回答
我的目标是捕获perl的发行外部命令的退出代码。 诀窍是,该外部指令信号实际上是由其中第一命令管道输送到第二命令两个命令。 对于我而言,我需要的第一个命令的退出代码。 Bash使用用于此目的的几种 可能的方式,例如
$ false | true; echo "${PIPESTATUS[0]}"
1
$ true | false; echo "${PIPESTATUS[0]}"
0
阅读关于这个问题后,我发现,perl的system
命令能够获取进程的退出代码,所以我尝试以下操作:
$ exit 10 | true
$ echo ${PIPESTATUS[0]}
10
$ true | false
$ echo $?
1
$ perl -e 'my $code = system("true | false"); print $code . "\n"'
256
$ perl -e 'my $code = system("bash -c \"true | false\""); print $code . "\n"'
256
$ perl -e 'my $code = system("bash -c \"exit 2\""); print $code . "\n"'
512
$ perl -e 'my $code = system("bash 2>&1 >/dev/null"); print $code . "\n"'
$ exit 10
exit
2560
正如你可以看到我正在从怪异的返回码(256,512,2560) system
命令。 我认为这是关系到我的另一个问题 。 到目前为止,我能够访问第一个命令的返回码的唯一可行的方法是使用qw
或backtickss``。 这似乎对我来说有点AA矫枉过正,因为我需要一个echo
捕捉PIPESTATUS[0]
值。
$ perl -e 'my $res = qx/true | false 2>&1 >\/dev\/null; echo \${PIPESTATUS[0]}/; print $res'
0
$ perl -e 'my $res = qx/false | true 2>&1 >\/dev\/null; echo \${PIPESTATUS[0]}/; print $res'
1
$ perl -e 'my $res = qx"false | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}"; print $res'
1
$ perl -e 'my $res = qx"true | false 2>&1 >/dev/null; echo \${PIPESTATUS[0]}"; print $res'
0
$ perl -e 'my $res = qx(false | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}); print $res'
1
$ perl -e 'my $res = `false | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}`; print $res'
1
我也想知道为什么这种方法甚至工作,因为这里提及的是,Perl不会调用shell执行外部命令。 那么,这是否PIPESTATUS
(这是一个纯bash的变量)从何而来? 我也期待下面的命令,因为bash将工作明确颁布,但它没有返回值:
$ perl -e 'my $res = `bash -c "false | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}"`; print $res'
$
第三小姐的理解是基于这个答案,我直接可以访问PIPESTATUS
通过将其分配给变量变量,然后作为普通的Perl变量如访问
status=(${PIPESTATUS[@]})
print $status
但是下面的命令不会为我工作。
$ perl -e 'my $res = `false | true 2>&1 >/dev/null;`; status=(${PIPESTATUS[@]})'
syntax error at -e line 1, near "@]}"
Missing right curly or square bracket at -e line 1, at end of line
Execution of -e aborted due to compilation errors.
@EDIT在回答ThisSuitIsBlackNot,TJD和CapEnt
返回码和比特移位解释:
$ perl -e 'my $code = system("true | false"); print $code >> 8; print "\n"'
1
$ perl -e 'my $code = system("bash -c \"true | false\""); print $code >> 8; print "\n"'
1
$ perl -e 'my $code = system("bash -c \"exit 2\""); print $code >> 8; print "\n"'
2
一些系统/bin/sh
指出bash
...
# Linux arch 3.18.6-1-ARCH #1 SMP PREEMPT Sat Feb 7 08:59:29 CET 2015 i686 GNU/Linux
$ ls -la `which sh`
lrwxrwxrwx 1 root root 4 Dec 30 23:11 /usr/bin/sh -> bash
$ perl -e 'my $cmd = "exit 255 | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}"; system($cmd);'
255
一些不...
# SunOS andromeda 5.9 Generic_122300-61 sun4u sparc SUNW,Sun-Fire-V490
$ ls -la `which sh`
-r-xr-xr-x 4 root root 95504 Jul 16 2009 /bin/sh
$ perl -e 'my $cmd = "exit 255 | true 2>&1 >/dev/null; echo \${PIPESTATUS[0]}"; system($cmd);'
sh: bad substitution
一个小黑客将使用bash
,无论什么/bin/sh
指向:
# Linux arch 3.18.6-1-ARCH #1 SMP PREEMPT Sat Feb 7 08:59:29 CET 2015 i686 GNU/Linux
# SunOS andromeda 5.9 Generic_122300-61 sun4u sparc SUNW,Sun-Fire-V490
$ perl -e 'my $cmd = "bash -c \"exit 255 | true 2>&1 >/dev/null; echo \\\${PIPESTATUS[0]}\""; system($cmd);'
255
在这里,您可以看到的bash在这两种情况下调用(在第二种情况bash
是儿童sh
)
# Linux arch 3.18.6-1-ARCH #1 SMP PREEMPT Sat Feb 7 08:59:29 CET 2015 i686 GNU/Linux
$ perl -e 'my $code = system("bash -c \"ps -elf | grep $$\"");'
0 S wakatana 1576 282 0 80 0 - 1606 wait 16:46 pts/1 00:00:00 perl -e my $code = system("bash -c \"ps -elf | grep $$\"");
0 S wakatana 1577 1576 0 80 0 - 1333 wait 16:46 pts/1 00:00:00 bash -c ps -elf | grep 1576
0 S wakatana 1579 1577 0 80 0 - 1167 pipe_w 16:46 pts/1 00:00:00 grep 1576
# SunOS andromeda 5.9 Generic_122300-61 sun4u sparc SUNW,Sun-Fire-V490
$ perl -e 'my $code = system("bash -c \"ps -elf | grep $$\"");'
8 S wakatana 24641 24640 0 60 20 ? 314 ? 16:01:45 pts/196 0:00 bash -c ps -elf | grep 24639
8 S wakatana 24640 24639 0 50 20 ? 139 ? 16:01:45 pts/196 0:00 sh -c bash -c "ps -elf | grep 24639
8 S wakatana 24643 24641 0 50 20 ? 128 ? 16:01:45 pts/196 0:00 grep 24639
8 S wakatana 24639 24633 0 50 20 ? 383 ? 16:01:45 pts/196 0:00 perl -e my $code = system("bash -c
作为ThisSuitIsBlackNot指出,可能是最好的解决办法是使用IPC ::运行 ,但我想知道如果这是确定的情况下,当我需要单纯的Perl(不含模块)