Яка різниця між задумами, системою та виконанням Perl?


237

Може хтось, будь ласка, допоможе мені? У Perl, яка різниця між:

exec "command";

і

system("command");

і

print `command`;

Чи є й інші способи запускати команди оболонки?


8
Майже точний дублікат stackoverflow.com/questions/797127/… , за винятком того, що у цього є exec, а в іншого є труби.
Майкл Майерс

Відповіді:


268

виконувати

виконує команду і ніколи не повертається . Це як returnтвердження у функції.

Якщо команда не знайдена, execповертається помилково. Він ніколи не повертає істину, тому що якщо команда знайдена, вона ніколи не повертається. Там також немає сенсу повертатися STDOUT, STDERRабо статус завершення команди. Ви можете знайти документацію про це perlfunc, оскільки це функція.

система

виконує команду, і ваш сценарій Perl продовжується після завершення команди.

Повернене значення - це стан виходу команди. Ви можете знайти документацію про це в perlfunc.

задній план

як systemвиконує команду, і ваш скрипт perl продовжується після завершення команди.

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


Інші способи

Чого не вистачає у вищезазначеному, це спосіб асинхронного виконання команди. Це означає, що ваш скрипт perl і ваша команда працюють одночасно. Це можна досягти за допомогою open. Це дозволяє читати STDOUT/ STDERRзаписувати на STDINвашу команду. Це залежить від платформи.

Також є кілька модулів, які можуть полегшити це завдання. Є IPC::Open2і IPC::Open3і IPC::Run, як і Win32::Process::Createякщо ви на вікнах.


1
Я думаю, ви маєте на увазі s / perlcunc / perlfunc / ... також документація на perlipc йде в глибину щодо відкриття труб.
ефемія

7
perlcunc, можливо, це буде моє нове прізвисько ;-)
Людвіг Вайнцерль,

8
Для запису, backticks і qx [] також заповнюють $? (повернене значення ОС).
jjohn

167

Загалом використанні I 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, але з дещо іншим порядком до аргументів і третьою файловою обробкою.


Дуже інформативна та актуальна відповідь. Спасибі @ Час-Оуенс
Jassi

IPC :: Open3 є занадто низьким рівнем для більшості застосувань. IPC :: Run3 та IPC :: Run, як правило, набагато доречніше.
ikegami

17

Дозвольте спочатку цитувати посібники:

perldoc exec () :

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

система Perldoc () :

Робиться точно так само, як і виконувати СПИСОК, за винятком того, що спочатку робиться вилка , і батьківський процес очікує завершення дочірнього процесу.

На відміну від exec та системи , backticks не дає значення повернення, а зібране STDOUT.

`String` perldoc :

Рядок, який (можливо) інтерполюється і потім виконується у вигляді системної команди з / 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 :: Запуск із CPAN також варто переглянути…


3
Це груба відповідь. Ви повинні намагатися бути корисними без гніву.
Шейн К. Мейсон

1
Я думаю, що він просто робив посилання на ol 'RTFM: P
v3.

насправді не малося на увазі грубо;) видалили слово f, хоча, щоб уникнути непорозумінь…
Benedikt Waldvogel,

2
Я, звичайно, не трактував це як грубе. Бруск, можливо, але це не високоінтелектуальне запитання, що вимагає продуманої відповіді.
ефемієнт

11

Яка різниця між задумами Perl ( `) system, та exec?

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

exec

execвиконує команду і ніколи не поновлює сценарій Perl. Це до сценарію, як returnзаява - до функції.

Якщо команда не знайдена, execповертає false. Він ніколи не повертає істину, тому що якщо команда знайдена, вона ніколи не повертається взагалі. Там також немає сенсу повертатися 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висловлювань на стандартне виведення.

backtikks ( `)

Мовляв system, вкладення команди в backticks виконує цю команду, і ваш скрипт Perl поновлюється після завершення команди. На відміну від system, значення, що повертається, є STDOUTкомандою. qx//еквівалентно задній план. Ви можете знайти документацію про це в perlop , тому що на відміну від system і 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

Різниця між "exec" і "system" полягає в тому, що exec замінює поточну програму на "команду", і НІКОЛИ не повертається до вашої програми. З іншого боку, система розкручує та виконує команду і повертає вам статус виходу "команда", коли вона виконана. Задня галочка виконує команду, а потім повертає рядок, що представляє її стандарт (усе, що було б надруковано на екрані)

Ви також можете використовувати popen для запуску команд оболонки, і я думаю, що є модуль оболонки - «використовувати оболонку», який надає прозорий доступ до типових команд оболонок.

Сподіваємось, що це вам роз’яснить.


Можливо, ви маєте на увазі use Shell;( search.cpan.org/dist/Shell/Shell.pm )? Це не широко встановлено, і це не стосується питання, я думаю ...
ephemient

1
Остання частина його питання полягала в тому, "чи є інші способи запускати команди оболонки" - Shell - це ще один спосіб запуску команд оболонки.
Шейн К. Мейсон

2
Документи конкретно заявляють: "Цей пакет включений у виставковий випадок, що ілюструє кілька функцій Perl. Він не повинен використовуватися для виробничих програм. Хоча він забезпечує простий інтерфейс для отримання стандартного виводу довільних команд, може бути краще способи досягнення того, що вам потрібно ».
Час. Овенс

2
Знову він відповів на його запитання "чи є інші способи"
Шейн К. Мейсон,

Погані, непідтримувані способи не повинні даватися без попереджень про те, що вони погані та непідтримувані.
Час. Овенс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.