В чем разница между бэкстиками Perl, системой и exec? - PullRequest
226 голосов
/ 29 апреля 2009

Может кто-нибудь, пожалуйста, помогите мне? В Perl какая разница между:

exec "command";

и

system("command");

и

print `command`;

Существуют ли другие способы запуска команд оболочки?

Ответы [ 5 ]

254 голосов
/ 29 апреля 2009

* Exec 1002 *

выполняет команду, а никогда не возвращает . Это как оператор return в функции.

Если команда не найдена, exec возвращает false. Он никогда не возвращает true, потому что, если команда найдена, она никогда не возвращается вообще. Также нет смысла возвращать STDOUT, STDERR или выходить из состояния команды. Вы можете найти документацию об этом в perlfunc, потому что это функция.

система

выполняет команду, и ваш Perl-скрипт продолжается после ее завершения.

Возвращаемым значением является состояние выхода команды. Вы можете найти документацию об этом в perlfunc.

* 1034 обратные кавычки *

подобно system выполняет команду, и ваш сценарий perl продолжается после ее завершения.

В отличие от system возвращаемое значение составляет STDOUT команды. qx// эквивалентно меткам. Вы можете найти документацию об этом в perlop, потому что в отличие от system и exec это оператор.


Другие способы

Чего не хватает в вышесказанном, так это способа выполнить команду асинхронно. Это означает, что ваш Perl-скрипт и ваша команда выполняются одновременно. Это можно сделать с помощью open. Это позволяет вам читать STDOUT / STDERR и записывать STDIN вашей команды. Это зависит от платформы.

Есть также несколько модулей, которые могут облегчить эту задачу. Существует IPC::Open2 и IPC::Open3 и IPC::Run, а также Win32::Process::Create если вы на окнах.

164 голосов
/ 29 апреля 2009

Обычно я использую system, open, IPC::Open2 или IPC::Open3 в зависимости от того, что я хочу сделать. Оператор qx//, хотя и прост, слишком ограничен в своей функциональности, чтобы быть очень полезным вне быстрых взломов. Я нахожу open намного удобнее.

system: запустить команду и дождаться ее возврата

Используйте system, если вы хотите запустить команду, не заботитесь о ее выводе и не хотите, чтобы скрипт Perl делал что-либо до ее завершения.

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

или

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx// или `` : запустить команду и перехватить ее STDOUT

Используйте qx//, когда вы хотите запустить команду, перехватите то, что она пишет в STDOUT, и не хотите, чтобы скрипт Perl делал что-либо, пока команда не завершится.

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec: заменить текущий процесс другим процессом.

Используйте exec вместе с fork, когда вы хотите запустить команду, не заботитесь о ее выводе и не хотите ждать ее возвращения. system на самом деле просто

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

Вы также можете прочитать инструкции waitpid и perlipc.

open: запустить процесс и создать канал для его STDIN или STDERR

Используйте open, если вы хотите записать данные в STDIN процесса или прочитать данные из STDOUT процесса (но не одновременно в оба).

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2 : запустить процесс и создать канал для STDIN и STDOUT

Используйте IPC::Open2, когда вам нужно читать и записывать в STDIN и STDOUT процесса.

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3 : запустить процесс и создать канал для STDIN, STDOUT и STDERR

используйте IPC::Open3, когда вам нужно захватить все три стандартных файловых дескриптора процесса. Я бы написал пример, но он работает в основном так же, как IPC :: Open2, но с несколько другим порядком аргументов и дескриптором третьего файла.

17 голосов
/ 29 апреля 2009

Позвольте мне сначала процитировать руководства:

perldoc exec () :

Функция exec выполняет системную команду и никогда не возвращает - используйте system вместо exec , если вы хотите, чтобы она возвратила

perldoc system () :

Действует точно так же, как exec LIST, за исключением того, что сначала выполняется ветвь , и родительский процесс ожидает завершения дочернего процесса.

В отличие от exec и system , обратные кавычки дают не возвращаемое значение, а собранный STDOUT.

perldoc & # x0060; String & # x0060; :

Строка, которая (возможно) интерполируется и затем выполняется как системная команда с / bin / sh или ее эквивалентом. Подстановочные знаки, трубы и перенаправления будут выполнены. Собранный стандартный вывод команды возвращается ; стандартная ошибка не изменяется.


Альтернативы:

В более сложных сценариях, когда вы хотите получить STDOUT, STDERR или код возврата, вы можете использовать хорошо известные стандартные модули, такие как IPC :: Open2 и IPC :: Open3 .

Пример: * * тысяча пятьдесят-четырь

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

Наконец, IPC :: Run из CPAN также стоит посмотреть…

9 голосов
/ 04 июня 2016

В чем разница между бэкксами Perl (`), system и exec?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

exec выполняет команду и никогда не возобновляет сценарий Perl. Это для сценария, как оператор return для функции.

Если команда не найдена, exec возвращает false. Он никогда не возвращает true, потому что, если команда найдена, она никогда не возвращается вообще. Также нет смысла возвращать STDOUT, STDERR или выходить из состояния команды. Вы можете найти документацию об этом в perlfunc , потому что это функция.

Например:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

В приведенном выше коде есть три print оператора, но из-за exec, покидающего скрипт, выполняется только первый оператор печати. Кроме того, вывод команды exec не присваивается какой-либо переменной.

Здесь только вы получаете вывод только первого оператора print и выполнения команды ls на стандартном выходе.

system

system выполняет команду, и ваш Perl-скрипт возобновляется после ее завершения. Возвращаемое значение является состоянием выхода команды. Вы можете найти документацию об этом в perlfunc .

Например:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

В приведенном выше коде есть три print оператора. Когда сценарий возобновляется после команды system, все три оператора печати выполняются.

Кроме того, результат выполнения system равен , назначенному data2, но назначенное значение равно 0 (код выхода из ls).

Здесь вы получаете выходные данные первого оператора print, затем команды ls, за которыми следуют выходные данные двух последних операторов print стандартного вывода.

backticks (`)

Как и system, включение команды в backticks выполняет эту команду, и ваш Perl-скрипт возобновляется после ее завершения. В отличие от system, возвращаемое значение составляет STDOUT команды. qx// эквивалентно меткам. Вы можете найти документацию об этом в perlop , потому что в отличие от системы и exec, это оператор.

Например:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

В приведенном выше коде есть три print оператора, и все три выполняются. Вывод ls не будет напрямую стандартизирован, но назначен переменной data2 и затем напечатан в последнем операторе печати. ​​

2 голосов
/ 29 апреля 2009

Разница между «exec» и «system» заключается в том, что exec заменяет вашу текущую программу на «command», и НИКОГДА не возвращается в вашу программу. Система, с другой стороны, разветвляется и запускает «команду» и возвращает вам состояние завершения «команды», когда она завершена. Обратный тик запускает команду и затем возвращает строку, представляющую его стандарт (вне зависимости от того, что он вывел бы на экран)

Вы также можете использовать popen для запуска команд оболочки, и я думаю, что есть модуль оболочки - 'use shell', который дает вам прозрачный доступ к типичным командам оболочки.

Надеюсь, это прояснит это для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...