为啥 IPC::Open3 调用 cmd.exe 而不是请求的程序?

Posted

技术标签:

【中文标题】为啥 IPC::Open3 调用 cmd.exe 而不是请求的程序?【英文标题】:Why is IPC::Open3 calling cmd.exe instead of the requested program?为什么 IPC::Open3 调用 cmd.exe 而不是请求的程序? 【发布时间】:2013-04-17 14:09:30 【问题描述】:

我在 Windows 7 上的 Perl 5.16.3 x64(用 VC10 编译)上运行它。

当我运行这样的事情时:

use strict;
use warnings;
use IPC::Open3;
use Symbol 'gensym';

my $command = q[perl -e "$| = 1; for (1..60)  print '.'; sleep 1 "];

my ($in, $out, $err);
$out = gensym;
$err = gensym;

my $pid = open3($in, $out, $err, $command);

在进程列表中可以看到IPC::Open3调用的实际命令是:

cmd.exe /x/d/c perl -e "$| = 1; for (1..60)  print '.'; sleep 1 "

这当然会创建一个带有实际调用的子进程:

perl -e "$| = 1; for (1..60)  print '.'; sleep 1 "

因此,我得到了对应于 cmd.exe 的 pid,而不是对应于 perl.exe 的。

该文档没有提及有关此调用顺序的任何内容或有关 Windows 上不同行为的任何内容。我这里没有 Linux/Unix 机器来测试它,但我敢打赌它不会在那里做类似的事情(如果有人可以测试,如果我错了,请告诉我)。

无论如何,我想知道为什么IPC::Open3 会这样做?为什么不在那个命令里直接调用perl呢?

提前感谢任何 cmets。

【问题讨论】:

【参考方案1】:

要执行一个shell命令,你需要一个shell。

system 一样,open3 具有以下调用约定:

open3(..., ..., ..., $SHELL_COMMAND)
open3(..., ..., ..., $PROG, @ONE_OR_MORE_ARGS)

以下内容不应调用 shell:

my @command = ('perl', '-e', '$| = 1; for (1..60)  print q.; sleep 1 ');
my $pid = open3($in, $out, $err, @command);

【讨论】:

很好的答案。我从没想过这两个约定之间存在实际差异。谢谢! :-) 同意@Francisco Zarabozo 的评论,很好的回答!

以上是关于为啥 IPC::Open3 调用 cmd.exe 而不是请求的程序?的主要内容,如果未能解决你的问题,请参考以下文章

IPC::Open3 在 Apache 下运行失败

Perl 行为差异关闭由 open() 产生的子进程与 IPC::Open3

如何影响 Perl IPC::Open3 输出的宽度?

IPC::Open3 的更多麻烦 [重复]

IPC::Open3 并确定孩子是不是正在等待输入

perl IPC:Open3 最小通过 perlcritic?