Почему IPC::Open3 вызывает cmd.exe вместо запрошенной программы?

Я запускаю это на Perl 5.16.3 x64 (скомпилированном с VC10) в Windows 7.

Когда я запускаю что-то вроде этого:

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 }"

Из-за этого я получаю pid, соответствующий cmd.exe, а не perl.exe.

В документации ничего не говорится об этом порядке вызовов или о другом поведении в Windows. У меня нет здесь Linux/Unix для тестирования, но держу пари, там ничего подобного не делается (если кто-то может протестировать, дайте мне знать, если я ошибаюсь).

В любом случае, мне интересно, зачем IPC::Open3 это делает? Почему он напрямую не вызывает Perl в этой команде?

Заранее спасибо за любые комментарии.


person Francisco Zarabozo    schedule 17.04.2013    source источник


Ответы (1)


Чтобы выполнить команду оболочки, вам нужна оболочка.

Как и system, open3 имеет следующее соглашение о вызовах:

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

Следующее не должно вызывать оболочку:

my @command = ('perl', '-e', '$| = 1; for (1..60) { print q{.}; sleep 1 }');
my $pid = open3($in, $out, $err, @command);
person ikegami    schedule 17.04.2013
comment
Отличный ответ. Я никогда не думал, что между этими двумя соглашениями есть реальная разница. Спасибо! :-) - person Francisco Zarabozo; 17.04.2013
comment
Согласен с комментарием @Francisco Zarabozo, отличный ответ! - person arkhamvm; 05.02.2014