击等PIPESTATUS等效的Perl [复制](Bash like PIPESTATUS equi

2019-10-21 19:41发布

这个问题已经在这里有一个答案:

  • 如何检查的第一个程序的状态在管道中的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(不含模块)

Answer 1:

系统的返回值必须向右8移位,如的perldoc说 。 喜欢:

perl -e 'my $code = system("false | true"); print $? >> 8 . "\n"'


文章来源: Bash like PIPESTATUS equivalent for perl [duplicate]