Jaka jest różnica między backlickami Perla, systemem i exec?


237

Czy ktoś może mi pomóc? W Perlu jaka jest różnica między:

exec "command";

i

system("command");

i

print `command`;

Czy są też inne sposoby uruchamiania poleceń powłoki?


8
Prawie dokładny duplikat stackoverflow.com/questions/797127/... , z wyjątkiem tego, że ten ma exec, a drugi ma potoki.
Michael Myers

Odpowiedzi:


268

exec

wykonuje polecenie i nigdy nie wraca . To jest jak returninstrukcja w funkcji.

Jeśli polecenie nie zostanie znalezione, execzwraca false. Nigdy nie zwraca prawdy, ponieważ jeśli polecenie zostanie znalezione, nigdy nie zwraca. Nie ma też sensu w powrocie STDOUT, STDERRlub stanu wyjścia polecenia. Możesz znaleźć dokumentację na ten temat perlfunc, ponieważ jest to funkcja.

system

wykonuje polecenie, a skrypt Perla jest kontynuowany po zakończeniu polecenia.

Wartość zwracana to status wyjścia polecenia. Dokumentację na ten temat można znaleźć w perlfunc.

backticks

jak systemwykonuje polecenie, a skrypt perla jest kontynuowany po zakończeniu polecenia.

W przeciwieństwie do systemwartości zwracanej STDOUTpolecenia. qx//jest równoważne z backticks. Możesz znaleźć dokumentację na ten temat perlop, ponieważ w przeciwieństwie do systemi execjest to operator.


Innymi słowy

Brakuje w powyższym sposobie wykonywania polecenia asynchronicznie. Oznacza to, że twój skrypt perla i twoje polecenie działają jednocześnie. Można to osiągnąć za pomocą open. Pozwala na odczyt STDOUT/ STDERRzapis STDINtwojego polecenia. Jest to jednak zależne od platformy.

Istnieje również kilka modułów, które mogą ułatwić to zadanie. Jest IPC::Open2i IPC::Open3a IPC::Run, a także Win32::Process::Create, jeśli są na oknach.


1
Wydaje mi się, że masz na myśli s / perlcunc / perlfunc / ... także dokumentacja perlipc wnika bardzo głęboko w otwieranie rur.
ephemient

7
perlcunc, może to będzie mój nowy pseudonim ;-)
Ludwig Weinzierl

8
Dla przypomnienia, backticks i qx [] również wypełniają $? (wartość zwracana przez system operacyjny).
Jan

167

W powszechnym użyciu I system, open, IPC::Open2, lub IPC::Open3w zależności od tego, co chcę robić. qx//Operator, natomiast proste, jest zbyt ograniczające jego funkcjonalność jest bardzo przydatna poza szybkimi hacki. Uważam, że openjest dużo bardziej poręczny.

system: uruchom polecenie i poczekaj na jego powrót

Użyj, systemgdy chcesz uruchomić polecenie, nie przejmuj się jego wynikiem i nie chcesz, aby skrypt Perla zrobił cokolwiek, dopóki polecenie się nie zakończy.

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

lub

#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//lub `` : uruchom polecenie i przechwyć jego STDOUT

Użyj, qx//gdy chcesz uruchomić polecenie, przechwyć to, co zapisuje do STDOUT, i nie chcesz, aby skrypt Perla zrobił cokolwiek, dopóki polecenie się nie skończy.

#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: zastąp bieżący proces innym.

Użyj execwraz z, forkgdy chcesz uruchomić polecenie, nie dbaj o jego wynik i nie chcesz czekać na jego powrót. systemjest naprawdę sprawiedliwy

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
}

Możesz także przeczytać instrukcje waitpidi perlipcinstrukcje.

open: uruchom proces i utwórz potok do jego STDIN lub STDERR

Użyj, opengdy chcesz zapisać dane do STDIN procesu lub odczytać dane z STDOUT procesu (ale nie oba jednocześnie).

#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 : uruchom proces i utwórz potok zarówno do STDIN, jak i STDOUT

Użyj, IPC::Open2gdy musisz czytać i zapisywać do STDIN i STDOUT procesu.

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 : uruchom proces i utwórz potok do STDIN, STDOUT i STDERR

używaj, IPC::Open3gdy chcesz przechwycić wszystkie trzy standardowe uchwyty plików procesu. Chciałbym napisać przykład, ale działa głównie tak samo jak IPC :: Open2, ale z nieco inną kolejnością niż argumenty i uchwytem trzeciego pliku.


Bardzo pouczająca i aktualna odpowiedź. Dzięki @ chas-owens
Jassi

IPC :: Open3 jest zbyt niski dla większości zastosowań. IPC :: Run3 i IPC :: Run są zwykle znacznie bardziej odpowiednie.
ikegami,

17

Pozwól mi najpierw zacytować instrukcje:

perldoc exec () :

Funkcja exec wykonuje polecenie systemowe i nigdy nie powraca - użyj systemu zamiast exec, jeśli chcesz, aby zwrócił

system perldoc () :

Robi dokładnie to samo co exec LIST, z tą różnicą, że najpierw wykonuje się rozwidlenie , a proces nadrzędny czeka na zakończenie procesu potomnego.

W przeciwieństwie do exec i system , backsticks nie dają wartości zwracanej, ale zebrane STDOUT.

perldoc `String` :

Ciąg, który jest (ewentualnie) interpolowany, a następnie wykonywany jako polecenie systemowe za pomocą / bin / sh lub jego odpowiednika. Symbole wieloznaczne powłoki, potoki i przekierowania będą honorowane. Zwrócono zebrane standardowe dane wyjściowe polecenia ; standardowy błąd pozostaje niezmieniony.


Alternatywy:

W bardziej złożonych scenariuszach, w których chcesz pobrać STDOUT, STDERR lub kod powrotu, możesz użyć dobrze znanych standardowych modułów, takich jak IPC :: Open2 i IPC :: Open3 .

Przykład:

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

Na koniec warto również spojrzeć na IPC :: Run z CPAN…


3
To jest niegrzeczna odpowiedź. Powinieneś starać się być pomocny bez gniewu.
Shane C. Mason

1
Myślę, że właśnie nawiązał do starej wersji RTFM: P
v3.

tak naprawdę nie miało to oznaczać niegrzeczności;) usunęłem słowo „f”, aby uniknąć nieporozumień…
Benedikt Waldvogel

2
Z pewnością nie interpretowałem tego jako niegrzecznego. Być może Brusque, ale nie jest to bardzo inteligentne pytanie wymagające przemyślanej odpowiedzi.
ephemient

11

Jaka jest różnica między backlickami Perla ( `) systemi exec?

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

exec

execwykonuje polecenie i nigdy nie wznawia skryptu Perl. To jest do skryptu, podobnie jak returninstrukcja do funkcji.

Jeśli polecenie nie zostanie znalezione, execzwraca false. Nigdy nie zwraca wartości true, ponieważ jeśli polecenie zostanie znalezione, nigdy się nie zwraca. Nie ma też sensu w powrocie STDOUT, STDERRlub stanu wyjścia polecenia. Dokumentację na ten temat można znaleźć w Perlfunc , ponieważ jest to funkcja.

Na przykład:

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

W powyższym kodzie znajdują się trzy printinstrukcje, ale z powodu execopuszczenia skryptu wykonywana jest tylko pierwsza instrukcja print. Ponadto dane execwyjściowe polecenia nie są przypisywane do żadnej zmiennej.

Tutaj tylko ty otrzymujesz wynik pierwszej printinstrukcji i wykonanials polecenia na standardowym wyjściu.

system

systemwykonuje polecenie, a skrypt Perla jest wznawiany po zakończeniu polecenia. Wartość zwracana to status wyjścia polecenia. Dokumentację na ten temat można znaleźć w Perlfunc .

Na przykład:

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

W powyższym kodzie są trzy print instrukcje. Ponieważ skrypt jest wznawiany po systemkomendzie, wykonywane są wszystkie trzy instrukcje drukowania.

Ponadto wynik działania system jest przypisany do data2, ale przypisana wartość to0 (kod wyjścia z ls).

Tutaj otrzymujesz wynik pierwszej printinstrukcji, a następnie wynikuls polecenia, a następnie wyniki dwóch ostatnichprint instrukcji na wyjściu standardowym.

backticks (` )

Podobnie system, umieszczenie polecenia w backticks powoduje wykonanie polecenia, a skrypt Perla jest wznawiany po zakończeniu polecenia. W przeciwieństwie do systemwartości zwracanej jest STDOUTpolecenie. qx//jest równoważne z backticks. Możesz znaleźć dokumentację na ten temat w Perlop , ponieważ w przeciwieństwie do systemu i execjest to operator.

Na przykład:

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

W powyższym kodzie znajdują się trzy printinstrukcje i wszystkie trzy są wykonywane. Dane wyjściowe lsnie wyjdą bezpośrednio poza standard, ale zostaną przypisane do zmiennej, data2a następnie wydrukowane przez końcową instrukcję print.


Najlepsze wyjaśnienie z przykładem. Wielkie dzięki.
Arslan Anwar,

2

Różnica między „exec” i „system” polega na tym, że exec zastępuje bieżący program „komendą” i NIGDY nie wraca do programu. system, z drugiej strony, rozwidla i uruchamia „polecenie” i zwraca status wyjścia „polecenia”, gdy jest on uruchomiony. Zaznaczenie tylne uruchamia „polecenie”, a następnie zwraca ciąg reprezentujący jego standardowe wyjście (cokolwiek by wydrukowało na ekranie)

Możesz także używać popen do uruchamiania poleceń powłoki i myślę, że istnieje moduł powłoki - „użyj powłoki”, który daje przejrzysty dostęp do typowych poleceń powłoki.

Mam nadzieję, że to ci wyjaśni.


Być może masz na myśli use Shell;( search.cpan.org/dist/Shell/Shell.pm )? Nie jest powszechnie instalowany, ani nie ma zastosowania do pytania, tak myślę ...
ephemient

1
Ostatnia część jego pytania brzmiała: „czy są też inne sposoby uruchamiania poleceń powłoki” - Shell to inny sposób uruchamiania poleceń powłoki.
Shane C. Mason

2
Dokumenty wyraźnie stwierdzają: „Ten pakiet jest dołączony jako pokaz, ilustrujący kilka funkcji Perla. Nie powinien być używany w programach produkcyjnych. Chociaż zapewnia prosty interfejs do uzyskiwania standardowego wyjścia dowolnych poleceń, może być lepszy sposoby osiągnięcia tego, czego potrzebujesz ”.
Chas. Owens

2
Znów odpowiedział na pytanie „czy są inne sposoby”
Shane C. Mason

Złe, nieobsługiwane sposoby nie powinny być podawane bez ostrzeżenia, że ​​są złe i nieobsługiwane.
Chas. Owens,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.