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

发布于 2024-08-02 10:25:34 字数 225 浏览 2 评论 0原文

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

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

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

返回 256。

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

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

returns -1 as expected (program crontab1 doesn't exist)

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

returns 256.

What is the way to check the status of the first (or both) programs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

残疾 2024-08-09 10:25:34

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

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

举个例子。

You are getting the exit status of the entire command, just as you should. If you want the exit status separately, you're going to have to run the commands separately.

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

as an example.

贪了杯 2024-08-09 10:25:34

如果您容忍使用除系统之外的其他东西,还有更简单的解决方案。例如,结果 IPC::Run 中的方法返回链的所有退出代码。

If you tolerate using something other than system, there are easier solutions. For example, the results method in IPC::Run returns all exit codes of the chain.

吾家有女初长成 2024-08-09 10:25:34

请记住,您应该使用 $?>>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 仍应为非零。

Remember, you're supposed to use $?>>8 to get the exit code, not $?

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

1

This ("pipefail") only works if your shell is bash 3. Cygwin and some Linux flavors ship with it; not sure about mac.

You should be aware that 256 is an error return. 0 is what you'd get on success:

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

0

I didn't know system returned -1 for a single command that isn't found, but $?>>8 should still be non-zero in that case.

水波映月 2024-08-09 10:25:34

[这是对另一个问题的回答,该问题作为与此问题的重复项而被关闭。]

执行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::Run 确实]。

[This was composed as an answer to another question which was closed as a duplicate of this one.]

Executing a shell command requires executing a shell. To that end,

system($shell_command)

is equivalent to

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

As such, all of your examples run a single program (/bin/sh). If you want the exit statuses of multiple children, you're going to need to have multiple children!

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 is rather low level. IPC::Run3 and/or IPC::Run can possibly make this easier. [Update: Indeed, IPC::Run does].

戏剧牡丹亭 2024-08-09 10:25:34

如果您想检查状态,请不要将它们全部放在同一个系统中。打开第一个程序的读取管道以获取其输出,然后打开另一个程序的另一个管道。

If you want to check the status, don't put them all in the same system. Open a reading pipe to the first program to get its output then open another pipe to the other program.

情魔剑神 2024-08-09 10:25:34

操作系统仅返回最后执行的程序的退出状态,如果操作系统不返回退出状态,perl 无法报告它。

除了单独运行每个程序并使用临时文件而不是管道之外,我不知道有什么方法可以获取管道中早期程序返回的退出代码。

The operating system returns an exit status only for the last program executed and if the OS doesn't return it, perl can't report it.

I don't know of any way to get at the exit code returned by earlier programs in a pipeline other than by running each individually and using temporary files instead of pipes.

未央 2024-08-09 10:25:34

如何检查第一个(或两个)程序的状态?

至少没有这样的方法,因为你已经构建了东西。如果您必须了解这些事情,您可能必须通过 fork()、exec() 和 waitpid() 自己管理子进程。

以下是您的代码片段中发生的大致情况。

  1. perlsystem() 生成一个 shell,并使用 perl *wait()*s 来终止该子进程。

  2. shell 设置管道:

    1. 管道读取端的子 shell *exec()*s grep
    2. 子 shell 无法在 $PATH 中的任何位置找到 crontab1,并且 *exit()*s 127(在我的系统上,即 127 是指示 shell 的位置)未能找到要运行的程序)。
  3. grep 检测其输入的文件结尾,并且没有匹配任何内容,*exit()*s 1。

  4. shell *exit()*s 带有管道中最后一个进程的退出代码,同样是 1.< /p>

  5. perl 检测到 shell 的退出代码为 1,这在 $? 中编码为 256。

    (256 >> 8 == 1)

What is the way to check the status of the first (or both) programs?

There is no such way, at least, not as you have constructed things. You may have to manage sub-processes yourself via fork(), exec() and waitpid() if you must know these things.

Here is roughly what is happening in your code fragment.

  1. perl's system() spawns a shell, and perl *wait()*s for that subprocess to terminate.

  2. The shell sets up a pipeline:

    1. a subshell *exec()*s grep on the read-end of the pipe
    2. a subshell fails to locate crontab1 anywhere in $PATH, and *exit()*s 127 (on my system, that is, where 127 is the shell indicating failure to find a program to run).
  3. grep detects end-of-file on its input and, having matched nothing, *exit()*s 1.

  4. The shell *exit()*s with the exit code of the last process in the pipeline, which, again, is 1.

  5. perl detects the shell's exit code of 1, which is encoded in $? as 256.

    (256 >> 8 == 1)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文