如何检查Perl system()管道中第一个程序的状态?

sbtkgmzw  于 2022-11-15  发布在  Perl
关注(0)|答案(7)|浏览(213)
perl -e 'system ("crontab1 -l");print $?'

按预期返回-1(程序crontab 1不存在)

perl -e 'system ("crontab1 -l|grep blah");print $?'

返回256。
检查第一个(或两个)程序状态的方法是什么?

x6yk4ghg

x6yk4ghg1#

您将获得整个命令的退出状态,正如您应该获得的那样。如果您希望单独获得退出状态,则必须单独运行这些命令。

#!/usr/bin/perl -e
system("crontab1 -l > /tmp/junk.txt"); print $?;
system("grep blah /tmp/junk.txt"); print $?;

作为一个例子。

68de4m5k

68de4m5k2#

如果您允许使用system以外的方法,则有更简单的解决方案。例如,IPC::Run中的results方法返回链的所有退出代码。

jk9hmnmh

jk9hmnmh3#

请记住,您应该使用$?〉〉8来获取退出代码,而不是$?

perl -e 'system("set -o pipefail;false | true");print $?>>8,"\n"'

1
这(“pipefail”)只在你的shell是bash 3的时候才起作用。Cygwin和一些Linux版本随附了它;我不确定Mac
你应该知道256是一个错误返回值。0是你在成功时得到的结果:

perl -e 'system("true");print $?>>8,"\n"'

0
我不知道系统会为一个找不到的命令返回-1,但是在这种情况下$?〉〉8应该仍然是非零的。

zpjtge22

zpjtge224#

[* 这是对另一个question的回答,该question已作为此question的副本关闭。*]
执行shell命令需要执行shell。为此,

system($shell_command)

相当于

system('/bin/sh', '-c', $shell_command)

因此,所有的例子都运行一个程序(/bin/sh),如果你想要多个子程序的退出状态,你就需要有多个子程序!

use IPC::Open3 qw( open3 );

open(local *CHILD1_STDIN, '<', '/dev/null')
   or die $!;

pipe(local *CHILD2_STDIN, local *CHILD1_STDOUT)
   or die $!;

my $child1_pid = open3(
   '<&CHILD1_STDIN',
   '>&CHILD1_STDOUT',
   '>&STDERR',
   'prog1', 'arg1', 'arg2',
);

my $child2_pid = open3(
   '<&CHILD2_STDIN',
   '>&STDOUT',
   '>&STDERR',
   'prog2', 'arg1', 'arg2',
);

my @pipe_status = map { waitpid($_, 0) } $child1_pid, $child2_pid;

IPC::Open 3是相当低的级别。IPC::Run 3和/或IPC::Run可能会使这更容易。[更新:实际上,IPC::运行does]。

piwo6bdm

piwo6bdm5#

如果你想检查状态,不要把它们都放在同一个系统中。打开一个阅读管道到第一个程序来获取它的输出,然后打开另一个管道到另一个程序。

q9yhzks0

q9yhzks06#

操作系统只返回最后执行的程序的退出状态,如果操作系统不返回,perl也不能报告它。
我不知道有什么方法可以得到管道中早期程序返回的退出代码,除了单独运行每个程序和使用临时文件而不是管道。

jdgnovmf

jdgnovmf7#

  • 检查第一个(或两个)程序状态的方法是什么?*

没有这样的方法,至少你没有构造过东西。如果你必须知道这些东西,你可能必须自己通过fork(),exec()和waitpid()来管理子进程。
下面是代码片段中大致发生的情况。

  1. perlsystem() 会产生一个shell,而perlwait() 会让该子进程终止。
    1.壳体设置有管道:
    1.在管道的读取端上创建subshell *exec()*s grep
  2. subshell无法在$PATH中的任何位置定位crontab1,并且 *exit()*s 127(在我的系统上,即,其中127是指示无法找到要运行的程序的shell)。
  3. grep在其输入上检测到文件尾,并且没有匹配任何内容,*exit()*s 1.
  4. shell exit() 带有管道中最后一个进程的退出代码,也是1。
  5. perl检测到shell的退出代码1,该代码在$?中编码为256。
    (256〉〉8 == 1)

相关问题