Die Links zu linux.about.com sind nicht hilfreich. Sie machen nicht aus der Ferne klar, wie sich die Ausführung eines Befehls oder einer Befehlspipeline mit 'exec' von der normalen Ausführung unterscheidet. Daher die Frage des OP "Was nützt exec?"
Jonathan Hartley
2
Stack Overflow ist eine Site für Programmier- und Entwicklungsfragen. Diese Frage scheint nicht zum Thema zu gehören, da es nicht um Programmierung oder Entwicklung geht. Weitere Informationen zu den Themen finden Sie hier in der Hilfe. Vielleicht ist Super User oder Unix & Linux Stack Exchange ein besserer Ort, um zu fragen.
JWW
Antworten:
281
Die execeingebauten Befehlsspiegelfunktionen im Kernel, auf execvederen Basis eine Familie basiert , die üblicherweise von C aufgerufen wird.
execErsetzt das aktuelle Programm im aktuellen Prozess, ohne forkeinen neuen Prozess zu erstellen. Es ist nicht etwas, das Sie in jedem Skript verwenden würden, das Sie schreiben, aber es ist gelegentlich nützlich. Hier sind einige Szenarien, die ich verwendet habe;
Wir möchten, dass der Benutzer ein bestimmtes Anwendungsprogramm ohne Zugriff auf die Shell ausführt. Wir könnten das Anmeldeprogramm in / etc / passwd ändern, aber vielleicht möchten wir, dass die Umgebungseinstellung aus Startdateien verwendet wird. In (sagen wir) .profilesagt die letzte Aussage so etwas wie:
exec appln-program
Jetzt gibt es keine Shell mehr, zu der man zurückkehren kann. Selbst wenn es appln-programabstürzt, kann der Endbenutzer nicht zu einer Shell gelangen, da diese nicht vorhanden ist - execsie hat sie ersetzt.
Wir möchten eine andere Shell als die in / etc / passwd verwenden. So dumm es auch scheinen mag, auf einigen Websites können Benutzer ihre Anmeldeshell nicht ändern. Bei einer Site, die ich kenne, haben alle angefangen csh, und alle haben einfach .logineinen Aufruf an ihre (csh-Startdatei) gesendet ksh. Während das funktionierte, lief ein streunender cshProzess und die Abmeldung war zweistufig, was verwirrend werden konnte. Also haben wir es geändert exec ksh, indem wir gerade das C-Shell-Programm durch die Korn-Shell ersetzt und alles einfacher gemacht haben (es gibt andere Probleme damit, wie die Tatsache, dass kshes sich nicht um eine Login-Shell handelt).
Nur um Prozesse zu speichern. Wenn wir anrufen prog1 -> prog2 -> prog3 -> prog4usw. und niemals zurückkehren, machen Sie jeden Anruf zu einem Exec. Es spart Ressourcen (zugegebenermaßen nicht viel, sofern es nicht wiederholt wird) und vereinfacht das Herunterfahren.
Sie haben offensichtlich execirgendwo verwendet gesehen , vielleicht könnten wir seine Verwendung rechtfertigen, wenn Sie den Code zeigen, der Sie nervt.
Bearbeiten : Ich habe festgestellt, dass meine Antwort oben unvollständig ist. Es gibt zwei Verwendungen von execin Shells wie kshund bash- zum Öffnen von Dateideskriptoren. Hier sind einige Beispiele:
exec 3< thisfile # open "thisfile" for reading on file descriptor 3
exec 4> thatfile # open "thatfile" for writing on file descriptor 4
exec 8<> tother # open "tother" for reading and writing on fd 8
exec 6>> other # open "other" for appending on file descriptor 6
exec 5<&0# copy read file descriptor 0 onto file descriptor 5
exec 7>&4# copy write file descriptor 4 onto 7
exec 3<&-# close the read file descriptor 3
exec 6>&-# close the write file descriptor 6
Beachten Sie, dass der Abstand hier sehr wichtig ist. Wenn Sie zwischen der fd-Nummer und dem Umleitungssymbol ein Leerzeichen einfügen exec, wird die ursprüngliche Bedeutung wiederhergestellt:
exec 3< thisfile # oops, overwrite the current program with command "3"
Es gibt mehrere Möglichkeiten , wie Sie diese, auf KSH Gebrauch verwenden können , read -uoder print -u, auf bash, zum Beispiel:
Es gibt auch eine andere Verwendung, die ich als sehr praktisch und erwähnenswert empfunden habe, da sie sich auf Python-Webanwendungen bezieht und etwas zwischen Ihren (fantastischen) Antworten 2 und 3 zu liegen scheint. Normalerweise führe ich wsgi-Webanwendungen (z. B. Django oder Flasche) über einen Supervisor aus , der ein Gunicorn anruft App: Letzteres erfordert bekanntermaßen einige Umgebungsvariablen. Es ist viel einfacher und wartbarer, Gunicorn über ein Shell-Skript auszuführen, das alles einrichtet und exec gunicorndem Supervisor schließlich die richtige PID zurückgibt.
gru
1
Die Dokumente sagen, dass execdies für die Umleitung verwendet werden kann:> Wenn kein Befehl angegeben ist, werden alle Umleitungen in der aktuellen Shell wirksam und der Rückgabestatus ist 0. Wenn ein Umleitungsfehler vorliegt, ist der Rückgabestatus 1. Aber wie geht das ? exectatsächlich arbeiten, um einen Dateideskriptor zu ändern? Warum wird dieser spezielle Befehl für diese Aufgabe ausgewählt? (Markdown schlägt gerade fehl?)
Eine andere Verwendung: Leiten Sie alle Ausgaben eines Skripts in eine Protokolldatei umexec >.\logfilename.log 2>&1
Hogan
1
@Carmageddon: &>ist eine bashErweiterung (siehe man bash) und Ihr Beispiel entspricht exec >/var/log/userdata.log 2>&1. Mit anderen Worten, es leitet stdout und stderr in diese Datei um. Die folgenden Befehle erben diese Umleitungen, sofern sie nicht zurückgesetzt werden. Sie werden jedoch ausgeführt.
Cdarke
41
Nur um die akzeptierte Antwort mit einer kurzen, für Neulinge geeigneten kurzen Antwort zu ergänzen, brauchen Sie sie wahrscheinlich nicht exec.
Wenn Sie noch hier sind, sollte die folgende Diskussion hoffentlich zeigen, warum. Wenn Sie rennen, sagen Sie,
sh -c 'command'
Sie führen eine shInstanz aus und beginnen dann commandals untergeordnetes Element dieser shInstanz. Wenn der commandVorgang abgeschlossen ist, wird auch die shInstanz beendet.
sh -c 'exec command'
führt eine shInstanz aus, ersetzt diese shInstanz dann durch die commandBinärdatei und führt diese stattdessen aus.
Natürlich sind beide in diesem begrenzten Kontext nutzlos; du willst einfach
command
Es gibt einige Randbedingungen, in denen die Shell ihre Konfigurationsdatei lesen oder die Umgebung auf andere Weise als Vorbereitung für die Ausführung einrichten soll command. Dies ist so ziemlich die einzige Situation, in der exec commandes nützlich ist.
Dies führt einige Dinge aus, um die Umgebung so vorzubereiten, dass sie das enthält, was benötigt wird. Sobald dies erledigt ist, ist die shInstanz nicht mehr erforderlich. Daher ist es eine (geringfügige) Optimierung, die shInstanz einfach durch den commandProzess zu ersetzen , anstatt shsie als untergeordneten Prozess auszuführen und darauf zu warten. Beenden Sie sie dann, sobald sie abgeschlossen ist.
Wenn Sie am Ende eines Shell-Skripts so viele Ressourcen wie möglich für einen umfangreichen Befehl freigeben möchten, möchten Sie execdiesen Befehl möglicherweise als Optimierung verwenden.
Wenn etwas zwingt SieFormal laufen , shaber sie wirklich laufen etwas anderes wollen, exec something elseist natürlich das Problem zu umgehen , die unerwünschte zu ersetzen shInstanz (wie zum Beispiel , wenn Sie wirklich Ihre eigene spiffy laufen wollen goshstatt , shaber bei Sie sind , die nicht in /etc/shellsso können Sie Geben Sie es nicht als Ihre Login-Shell an.
Die zweite Verwendung execzum Bearbeiten von Dateideskriptoren ist ein separates Thema. Die akzeptierte Antwort deckt das gut ab; Um dies in sich geschlossen zu halten, werde ich nur auf das Handbuch zurückgreifen, execwenn eine Umleitung anstelle eines Befehlsnamens folgt.
Widerstehen Sie der Versuchung, Ihre eigene schicke Muschel zu nennen bush. Dies gilt natürlich auch für bashoder allgemein für jede beliebte Unix-Shell. Wie @anishsane bemerkt , optimiert Bash heimlich, bash -c 'command'indem er es tatsächlich tut exec command.
Tripleee
1
Der Exit-Code der Shell ist im Allgemeinen der Exit-Code des zuletzt ausgeführten Befehls. Wenn die Shell nicht ausgeführt oder der Befehl nicht ausgeführt werden kann, spiegelt der Exit-Status der Shell dies natürlich mit einem geeigneten Fehlercode wider.
Tripleee
2
@ JonathanLeffler Ich dokumentiere absichtlich ein Antimuster, das ich in Fragen von Neulingen sehe. Dieser wurde durch dieses Duplikat veranlasst, aber ich habe es schon einmal gesehen, deshalb wollte ich das speziell behandeln.
Tripleee
2
@ JonathanLeffler Kleinere Formulierungsänderungen; ist das ausreichend, denkst du? Danke für die Rückmeldung.
Tripleee
2
Danke - ich habe einen weiteren kurzen Absatz über diese Optimierung hinzugefügt. Mir ist nicht wirklich klar, ob Sie andere Einwände haben oder nur Dinge aus einem anderen Blickwinkel erklären möchten.
Antworten:
Die
exec
eingebauten Befehlsspiegelfunktionen im Kernel, aufexecve
deren Basis eine Familie basiert , die üblicherweise von C aufgerufen wird.exec
Ersetzt das aktuelle Programm im aktuellen Prozess, ohnefork
einen neuen Prozess zu erstellen. Es ist nicht etwas, das Sie in jedem Skript verwenden würden, das Sie schreiben, aber es ist gelegentlich nützlich. Hier sind einige Szenarien, die ich verwendet habe;Wir möchten, dass der Benutzer ein bestimmtes Anwendungsprogramm ohne Zugriff auf die Shell ausführt. Wir könnten das Anmeldeprogramm in / etc / passwd ändern, aber vielleicht möchten wir, dass die Umgebungseinstellung aus Startdateien verwendet wird. In (sagen wir)
.profile
sagt die letzte Aussage so etwas wie:Jetzt gibt es keine Shell mehr, zu der man zurückkehren kann. Selbst wenn es
appln-program
abstürzt, kann der Endbenutzer nicht zu einer Shell gelangen, da diese nicht vorhanden ist -exec
sie hat sie ersetzt.Wir möchten eine andere Shell als die in / etc / passwd verwenden. So dumm es auch scheinen mag, auf einigen Websites können Benutzer ihre Anmeldeshell nicht ändern. Bei einer Site, die ich kenne, haben alle angefangen
csh
, und alle haben einfach.login
einen Aufruf an ihre (csh-Startdatei) gesendetksh
. Während das funktionierte, lief ein streunendercsh
Prozess und die Abmeldung war zweistufig, was verwirrend werden konnte. Also haben wir es geändertexec ksh
, indem wir gerade das C-Shell-Programm durch die Korn-Shell ersetzt und alles einfacher gemacht haben (es gibt andere Probleme damit, wie die Tatsache, dassksh
es sich nicht um eine Login-Shell handelt).Nur um Prozesse zu speichern. Wenn wir anrufen
prog1 -> prog2 -> prog3 -> prog4
usw. und niemals zurückkehren, machen Sie jeden Anruf zu einem Exec. Es spart Ressourcen (zugegebenermaßen nicht viel, sofern es nicht wiederholt wird) und vereinfacht das Herunterfahren.Sie haben offensichtlich
exec
irgendwo verwendet gesehen , vielleicht könnten wir seine Verwendung rechtfertigen, wenn Sie den Code zeigen, der Sie nervt.Bearbeiten : Ich habe festgestellt, dass meine Antwort oben unvollständig ist. Es gibt zwei Verwendungen von
exec
in Shells wieksh
undbash
- zum Öffnen von Dateideskriptoren. Hier sind einige Beispiele:Beachten Sie, dass der Abstand hier sehr wichtig ist. Wenn Sie zwischen der fd-Nummer und dem Umleitungssymbol ein Leerzeichen einfügen
exec
, wird die ursprüngliche Bedeutung wiederhergestellt:Es gibt mehrere Möglichkeiten , wie Sie diese, auf KSH Gebrauch verwenden können ,
read -u
oderprint -u
, aufbash
, zum Beispiel:quelle
exec gunicorn
dem Supervisor schließlich die richtige PID zurückgibt.exec
dies für die Umleitung verwendet werden kann:> Wenn kein Befehl angegeben ist, werden alle Umleitungen in der aktuellen Shell wirksam und der Rückgabestatus ist 0. Wenn ein Umleitungsfehler vorliegt, ist der Rückgabestatus 1. Aber wie geht das ?exec
tatsächlich arbeiten, um einen Dateideskriptor zu ändern? Warum wird dieser spezielle Befehl für diese Aufgabe ausgewählt? (Markdown schlägt gerade fehl?)exec >.\logfilename.log 2>&1
&>
ist einebash
Erweiterung (sieheman bash
) und Ihr Beispiel entsprichtexec >/var/log/userdata.log 2>&1
. Mit anderen Worten, es leitet stdout und stderr in diese Datei um. Die folgenden Befehle erben diese Umleitungen, sofern sie nicht zurückgesetzt werden. Sie werden jedoch ausgeführt.Nur um die akzeptierte Antwort mit einer kurzen, für Neulinge geeigneten kurzen Antwort zu ergänzen, brauchen Sie sie wahrscheinlich nicht
exec
.Wenn Sie noch hier sind, sollte die folgende Diskussion hoffentlich zeigen, warum. Wenn Sie rennen, sagen Sie,
Sie führen eine
sh
Instanz aus und beginnen danncommand
als untergeordnetes Element diesersh
Instanz. Wenn dercommand
Vorgang abgeschlossen ist, wird auch diesh
Instanz beendet.führt eine
sh
Instanz aus, ersetzt diesesh
Instanz dann durch diecommand
Binärdatei und führt diese stattdessen aus.Natürlich sind beide in diesem begrenzten Kontext nutzlos; du willst einfach
Es gibt einige Randbedingungen, in denen die Shell ihre Konfigurationsdatei lesen oder die Umgebung auf andere Weise als Vorbereitung für die Ausführung einrichten soll
command
. Dies ist so ziemlich die einzige Situation, in derexec command
es nützlich ist.Dies führt einige Dinge aus, um die Umgebung so vorzubereiten, dass sie das enthält, was benötigt wird. Sobald dies erledigt ist, ist die
sh
Instanz nicht mehr erforderlich. Daher ist es eine (geringfügige) Optimierung, diesh
Instanz einfach durch dencommand
Prozess zu ersetzen , anstattsh
sie als untergeordneten Prozess auszuführen und darauf zu warten. Beenden Sie sie dann, sobald sie abgeschlossen ist.Wenn Sie am Ende eines Shell-Skripts so viele Ressourcen wie möglich für einen umfangreichen Befehl freigeben möchten, möchten Sie
exec
diesen Befehl möglicherweise als Optimierung verwenden.Wenn etwas zwingt SieFormal laufen ,
sh
aber sie wirklich laufen etwas anderes wollen,exec something else
ist natürlich das Problem zu umgehen , die unerwünschte zu ersetzensh
Instanz (wie zum Beispiel , wenn Sie wirklich Ihre eigene spiffy laufen wollengosh
statt ,sh
aber bei Sie sind , die nicht in/etc/shells
so können Sie Geben Sie es nicht als Ihre Login-Shell an.Die zweite Verwendung
exec
zum Bearbeiten von Dateideskriptoren ist ein separates Thema. Die akzeptierte Antwort deckt das gut ab; Um dies in sich geschlossen zu halten, werde ich nur auf das Handbuch zurückgreifen,exec
wenn eine Umleitung anstelle eines Befehlsnamens folgt.quelle
bush
. Dies gilt natürlich auch fürbash
oder allgemein für jede beliebte Unix-Shell. Wie @anishsane bemerkt , optimiert Bash heimlich,bash -c 'command'
indem er es tatsächlich tutexec command
.