perl -e 'system ("crontab1 -l");print $?'
按预期返回-1(程序crontab1不存在)
perl -e 'system ("crontab1 -l|grep blah");print $?'
返回256。
检查第一个(或两个)程序状态的方法是什么?
答案 0 :(得分:4)
您正在获得整个命令的退出状态,就像您应该的那样。如果您想单独退出状态,则必须单独运行命令。
#!/usr/bin/perl -e
system("crontab1 -l > /tmp/junk.txt"); print $?;
system("grep blah /tmp/junk.txt"); print $?;
作为一个例子。
答案 1 :(得分:4)
如果您容忍使用system
以外的其他内容,则可以使用更简单的解决方案。例如,the results
method in IPC::Run返回链的所有退出代码。
答案 2 :(得分:3)
请记住,您应该使用$?>> 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仍应为非零。
答案 3 :(得分:2)
[这是作为另一个question的答案而作出的,该does作为此副本的副本而被关闭。]
执行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 :: Open3相当低级。 IPC :: Run3和/或IPC :: Run可以使这更容易。 [更新:确实,IPC ::运行{{3}}]。
答案 4 :(得分:1)
如果要检查状态,请不要将它们全部放在同一系统中。打开第一个程序的读取管道以获取其输出,然后打开另一个管道到另一个程序。
答案 5 :(得分:1)
操作系统仅为最后执行的程序返回退出状态,如果操作系统没有返回,则perl无法报告。
我不知道如何获取管道中早期程序返回的退出代码,而不是单独运行每个程序并使用临时文件而不是管道。
答案 6 :(得分:1)
检查第一个(或两个)程序状态的方法是什么?
至少没有这样的方式,不是因为你已经构建了东西。如果你必须知道这些事情,你可能必须通过fork(),exec()和waitpid()自己管理子进程。
以下是您的代码片段中发生的情况。
perl
的 system()生成一个shell,perl
* wait()* s为该子进程终止。
shell设置了一个管道:
grep
crontab1
中找到$PATH
,并且* exit()* s 127(在我的系统上,也就是说,其中127是shell,表示无法找到要运行的程序) )。 grep
检测到其输入文件的结尾,并且没有匹配,* exit()* s 1.
shell * exit()* s,其中包含管道中最后一个进程的退出代码,该代码再次为1.
perl
检测到shell的退出代码为1,该代码以$?
编码为256。
(256>&gt; 8 == 1)