Was ist der Unterschied zwischen Perls Backticks, System und Exec?


237

Kann mir bitte jemand helfen? Was ist in Perl der Unterschied zwischen:

exec "command";

und

system("command");

und

print `command`;

Gibt es auch andere Möglichkeiten, Shell-Befehle auszuführen?


8
Fast ein genaues Duplikat von stackoverflow.com/questions/797127/… , außer dass dieses Exec und das andere Pipes hat.
Michael Myers

Antworten:


268

exec

führt einen Befehl aus und kehrt nie zurück . Es ist wie eine returnAussage in einer Funktion.

Wenn der Befehl nicht gefunden wird, wird execfalse zurückgegeben. Es wird niemals true zurückgegeben, da der Befehl niemals zurückgegeben wird, wenn er gefunden wird. Es macht auch keinen Sinn STDOUT, STDERRden Befehl zurückzugeben oder zu beenden. Dokumentation dazu finden Sie in perlfunc, da es sich um eine Funktion handelt.

System

führt einen Befehl aus und Ihr Perl-Skript wird fortgesetzt, nachdem der Befehl beendet wurde.

Der Rückgabewert ist der Exit-Status des Befehls. Dokumentation dazu finden Sie in perlfunc.

Backticks

like systemführt einen Befehl aus und Ihr Perl-Skript wird fortgesetzt, nachdem der Befehl beendet wurde.

Im Gegensatz zum systemRückgabewert steht STDOUTder Befehl. qx//entspricht Backticks. Sie können Dokumentation darüber in finden perlop, denn im Gegensatz zu systemund execes ein Operator ist.


Andere Möglichkeiten

Was oben fehlt, ist eine Möglichkeit, einen Befehl asynchron auszuführen. Das bedeutet, dass Ihr Perl-Skript und Ihr Befehl gleichzeitig ausgeführt werden. Dies kann mit erreicht werden open. Sie können damit Ihren Befehl lesen STDOUT/ STDERRschreiben STDIN. Es ist jedoch plattformabhängig.

Es gibt auch mehrere Module, die diese Aufgaben erleichtern können. Es gibt IPC::Open2und IPC::Open3und IPC::Run, sowie Win32::Process::Createwenn Sie unter Windows sind.


1
Ich denke du meinst s / perlcunc / perlfunc / ... auch die perlipc Dokumentation geht sehr tief in das Öffnen von Rohren ein.
Ephemient

7
perlcunc, vielleicht ist das mein neuer Spitzname ;-)
Ludwig Weinzierl

8
Für die Aufzeichnung füllen Backticks und qx [] auch $? (der OS-Rückgabewert).
John

167

Im Allgemeinen ich Gebrauch system, open, IPC::Open2, oder IPC::Open3je nachdem , was ich tun möchte. Der qx//Bediener ist zwar einfach, aber in seiner Funktionalität zu eingeschränkt, um außerhalb schneller Hacks sehr nützlich zu sein. Ich finde openzu viel handlicher.

system: Führen Sie einen Befehl aus und warten Sie, bis er zurückkehrt

Verwenden systemSie diese Option, wenn Sie einen Befehl ausführen möchten, sich nicht um dessen Ausgabe kümmern möchten und das Perl-Skript nichts tun soll, bis der Befehl beendet ist.

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

oder

#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//oder `` : Führen Sie einen Befehl aus und erfassen Sie dessen STDOUT

Verwenden qx//Sie diese Option, wenn Sie einen Befehl ausführen, erfassen möchten, was in STDOUT geschrieben wird, und nicht möchten, dass das Perl-Skript etwas tut, bis der Befehl beendet ist.

#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: Ersetzen Sie den aktuellen Prozess durch einen anderen Prozess.

Verwenden Sie diese Option execzusammen mit, forkwenn Sie einen Befehl ausführen möchten, sich nicht um seine Ausgabe kümmern und nicht darauf warten möchten, dass er zurückgegeben wird. systemist wirklich gerecht

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
}

Vielleicht möchten Sie auch die Handbücher waitpidund lesen perlipc.

open: Führen Sie einen Prozess aus und erstellen Sie eine Pipe zu STDIN oder STDERR

Verwenden openSie diese Option, wenn Sie Daten in die STDIN eines Prozesses schreiben oder Daten aus der STDOUT eines Prozesses lesen möchten (jedoch nicht beide gleichzeitig).

#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 : Führen Sie einen Prozess aus und erstellen Sie eine Pipe zu STDIN und STDOUT

Verwenden IPC::Open2Sie diese Option, wenn Sie aus STDIN und STDOUT eines Prozesses lesen und in diesen schreiben müssen.

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 : Führen Sie einen Prozess aus und erstellen Sie eine Pipe zu STDIN, STDOUT und STDERR

Verwenden IPC::Open3Sie diese Option, wenn Sie alle drei Standard-Dateihandles des Prozesses erfassen müssen. Ich würde ein Beispiel schreiben, aber es funktioniert meistens genauso wie IPC :: Open2, jedoch mit einer etwas anderen Reihenfolge als die Argumente und einem dritten Dateihandle.


Sehr informative und aktuelle Antwort. Danke @ chas-owens
Jassi

IPC :: Open3 ist für die meisten Anwendungen zu niedrig. IPC :: Run3 und IPC :: Run sind normalerweise weitaus geeigneter.
Ikegami

17

Lassen Sie mich zuerst die Handbücher zitieren:

perldoc exec () :

Die exec-Funktion führt einen Systembefehl aus und gibt niemals zurück. Verwenden Sie system anstelle von exec, wenn Sie möchten, dass es zurückkehrt

Perldoc-System () :

Führt genau das Gleiche aus wie exec LIST, außer dass zuerst eine Verzweigung ausgeführt wird und der übergeordnete Prozess auf den Abschluss des untergeordneten Prozesses wartet.

Im Gegensatz zu exec und system geben Backticks nicht den Rückgabewert, sondern den gesammelten STDOUT.

perldoc `String` :

Eine Zeichenfolge, die (möglicherweise) interpoliert und dann als Systembefehl mit / bin / sh oder einem entsprechenden Befehl ausgeführt wird . Shell-Platzhalter, Pipes und Weiterleitungen werden berücksichtigt. Die gesammelte Standardausgabe des Befehls wird zurückgegeben . Standardfehler bleibt unberührt.


Alternativen:

In komplexeren Szenarien, in denen Sie STDOUT, STDERR oder den Rückkehrcode abrufen möchten, können Sie bekannte Standardmodule wie IPC :: Open2 und IPC :: Open3 verwenden .

Beispiel:

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

Schließlich ist auch IPC :: Run aus dem CPAN einen Blick wert…


3
Dies ist eine unhöfliche Antwort. Sie sollten versuchen, ohne Ärger hilfreich zu sein.
Shane C. Mason

1
Ich denke, er hat nur auf das alte RTFM Bezug genommen: P
v3.

war eigentlich nicht unhöflich gemeint;) entfernte das f-Wort allerdings, um Missverständnisse zu vermeiden…
Benedikt Waldvogel

2
Ich habe es sicherlich nicht als unhöflich interpretiert. Brusque vielleicht, aber dies ist keine hochintelligente Frage, die eine nachdenkliche Antwort erfordert.
Ephemient

11

Was ist der Unterschied zwischen Perls Backticks ( `) systemund exec?

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

exec

execführt einen Befehl aus und setzt das Perl-Skript nie fort. Es ist für ein Skript wie eine returnAnweisung für eine Funktion.

Wenn der Befehl nicht gefunden wird, wird execfalse zurückgegeben. Es wird niemals true zurückgegeben, da der Befehl niemals zurückgegeben wird, wenn er gefunden wird. Es macht auch keinen Sinn STDOUT, STDERRden Befehl zurückzugeben oder zu beenden. Dokumentation dazu finden Sie in perlfunc , da es sich um eine Funktion handelt.

Z.B:

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

Im obigen Code gibt es drei printAnweisungen, aber aufgrund des execVerlassens des Skripts wird nur die erste print-Anweisung ausgeführt. Außerdem wird die execBefehlsausgabe keiner Variablen zugewiesen.

Hier erhalten nur Sie nur die Ausgabe der ersten printAnweisung und die Ausführung des lsBefehls auf Standardausgabe.

system

systemführt einen Befehl aus und Ihr Perl-Skript wird fortgesetzt, nachdem der Befehl beendet wurde. Der Rückgabewert ist der Exit-Status des Befehls. Dokumentation dazu finden Sie in perlfunc .

Z.B:

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

Im obigen Code gibt es drei printAnweisungen. Wenn das Skript nach dem systemBefehl fortgesetzt wird , werden alle drei Druckanweisungen ausgeführt.

Auch das Ergebnis des Laufens system wird zugewiesen data2, aber der zugewiesene Wert ist 0(der Exit-Code von ls).

Hier erhalten Sie die Ausgabe der ersten printAnweisung, dann die des lsBefehls, gefolgt von den Ausgaben der letzten beiden printAnweisungen für standard out.

backticks ( `)

Wie system, einen Befehl in Backticks ausführen, Befehl und Ihr Perl - Skript wieder aufgenommen wird einschließt , nachdem der Befehl beendet ist. Im Gegensatz dazu systemist der Rückgabewert STDOUTder Befehl. qx//entspricht Backticks. Dokumentation dazu finden Sie in Perlop , da es sich im Gegensatz zu system und execum einen Operator handelt.

Z.B:

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

Im obigen Code gibt es drei printAnweisungen und alle drei werden ausgeführt. Die Ausgabe von lswird nicht direkt standardisiert, sondern der Variablen zugewiesen data2und dann von der endgültigen Druckanweisung gedruckt.


Beste Erklärung mit Beispiel. Vielen Dank.
Arslan Anwar

2

Der Unterschied zwischen 'exec' und 'system' besteht darin, dass exec Ihr aktuelles Programm durch 'command' ersetzt und NIEMALS zu Ihrem Programm zurückkehrt. Das System hingegen gabelt und führt 'Befehl' aus und gibt Ihnen den Beendigungsstatus von 'Befehl' zurück, wenn es ausgeführt wird. Das Zurück-Häkchen führt 'Befehl' aus und gibt dann eine Zeichenfolge zurück, die den Standardausgang darstellt (was auch immer auf dem Bildschirm gedruckt worden wäre).

Sie können popen auch verwenden, um Shell-Befehle auszuführen, und ich denke, dass es ein Shell-Modul gibt - 'use shell', mit dem Sie transparent auf typische Shell-Befehle zugreifen können.

Hoffe das klärt es für dich.


Vielleicht meinst du use Shell;( search.cpan.org/dist/Shell/Shell.pm )? Es ist nicht weit verbreitet, noch ist es auf die Frage anwendbar, denke ich ...
Ephemient

1
Der letzte Teil seiner Frage lautete: "Gibt es auch andere Möglichkeiten, Shell-Befehle auszuführen?" - Shell ist eine andere Möglichkeit, Shell-Befehle auszuführen.
Shane C. Mason

2
In den Dokumenten heißt es ausdrücklich: "Dieses Paket ist als Vitrine enthalten und veranschaulicht einige Perl-Funktionen. Es sollte nicht für Produktionsprogramme verwendet werden. Obwohl es eine einfache Schnittstelle zum Abrufen der Standardausgabe beliebiger Befehle bietet, gibt es möglicherweise bessere." Wege, um das zu erreichen, was Sie brauchen. "
Chas. Owens

2
Wieder beantwortete es seine Frage "
Shane C. Mason

Schlechte, nicht unterstützte Wege sollten nicht ohne Warnungen angegeben werden, dass sie schlecht und nicht unterstützt sind.
Chas. Owens
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.