Anwendungsfall / praktisches Beispiel für Bash 'builtin exec

12

Beachten Sie dies aus der Dokumentation von Bash 'builtin exec:

exec ersetzt die Shell, ohne einen neuen Prozess zu erstellen

Bitte geben Sie einen Anwendungsfall / ein praktisches Beispiel an. Ich verstehe nicht, wie das Sinn macht.

Ich habe gegoogelt und etwas über die E / A-Umleitung herausgefunden . Kannst du es besser erklären?

Ivanov
quelle
unix.stackexchange.com/search?q=exec+shell+-find für einige Beispiele
Stéphane Chazelas

Antworten:

18

execwird häufig in Shell-Skripten verwendet, die hauptsächlich als Wrapper zum Starten anderer Binärdateien dienen. Beispielsweise:

#!/bin/sh

if stuff;
    EXTRA_OPTIONS="-x -y -z"
else
    EXTRA_OPTIONS="-a foo"
fi

exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"

Nach Beendigung der Ausführung des Wrappers übernimmt die "echte" Binärdatei und es ist keine Spur des Wrapperskripts mehr vorhanden, die vorübergehend denselben Steckplatz in der Prozesstabelle belegt hat. Die "echte" Binärdatei ist ein direktes Kind dessen, was sie anstelle eines Enkelkindes gestartet hat.

Sie erwähnen in Ihrer Frage auch die E / A-Umleitung. Das ist ein ganz anderer Anwendungsfall execund hat nichts damit zu tun, die Shell durch einen anderen Prozess zu ersetzen. Wann exechat keine Argumente, wie so:

exec 3>>/tmp/logfile

Die E / A-Umleitungen in der Befehlszeile werden im aktuellen Shell-Prozess wirksam, der aktuelle Shell-Prozess wird jedoch weiterhin ausgeführt und fährt mit dem nächsten Befehl im Skript fort.

Celada
quelle
1
Sie können sagen, dass die beiden Fälle darin zusammenhängen, dass für beide execdie Shell anweist, die Aktion nicht in einem untergeordneten Prozess, sondern in demselben Prozess auszuführen (einen Befehl auszuführen oder eine Umleitung auszuführen).
Stéphane Chazelas
5

Ich habe eine execeingebaute Shell verwendet, um eine Prozess-ID (PID) für ein Java-Programm zu erhalten. Möglicherweise gibt es jetzt eine Möglichkeit, PID aus Java heraus abzurufen, vor einigen Jahren jedoch noch nicht. Sobald ein Prozess eine eigene PID hat, kann er diese in eine PID-Datei schreiben (nach /var/run/Dateinamen mit dem Suffix '.pid' suchen), damit Verwaltungsprogramme die PID des ausgeführten Prozesses kennen und eine zweite Instanz verhindern können desselben Servers vom Laufen. Es funktioniert ungefähr so:

exec java -cp=YourServer.jar StartClass -p $$

Code in der main()Methode der Klasse StartClassverarbeitet das Parsen von Argumenten und kann seine eigene Prozess-ID finden.

Bruce Ediger
quelle
2

Führen Sie zum Spaß das folgende Programm (übersetzt in die Implementierungssprache Ihrer Wahl) im Hintergrund auf einem System mit Benutzerprozessabrechnung und Grenzwerten aus.

while(true) fork();

Nun, da jeder Slot in der Prozesstabelle, den Sie verwenden dürfen, voll mit Kopien dieses laufenden Programms ist, wie beabsichtigen Sie, es zu töten? Das Starten von kill (1) erfordert einen anderen Prozess-Slot, den Sie nicht haben können. Es wäre sicher praktisch, wenn die Shell sich selbst durch den Befehl kill ersetzen würde ...

exec /bin/kill -9 -1

(Angenommen, Ihr System hat kill (1) unter / bin / kill. "Exec` which kill` -9 -1 "ist möglicherweise sicherer.) Dies sendet SIGKILL an jeden Prozess, den Sie können.

(Hinweis: Melden Sie sich nicht von Ihrer Startshell ab, es sei denn, die Prozessbeschränkungen erlauben immer ein erneutes Anmelden eines Prozessfensters für die Shell. Dies kann etwas schwieriger zu bereinigen sein, wenn Sie dies tun Anfang der 90er Jahre.

Eric Towers
quelle
3
(1) Diese Antwort wäre etwas besser, wenn Sie tatsächlich den execBefehl zeigen würden, der in dieser Situation nützlich wäre. (2) Diese Antwort ist etwas archaisch; Das killKommando ist seit vielen Jahren ein eingebautes Kommando in Bash, hauptsächlich wegen dieser Besorgnis.
G-Man sagt, dass Monica am
@ G-Man: Hast du verstanden, dass dein Item (2) diese Antwort zu einer präzisen Antwort auf das OP macht?
Eric Towers
Nein, das verstehe ich nicht. Bitte erklären Sie es mir.
G-Man sagt, dass Monica am
4
Ich folge dir nicht. Die Frage fragt nicht nach praktischen Beispielen für alle in Bash eingebauten Befehle. es fragt nach Beispielen von exec- und die Tatsache, dass killes sich um ein eingebautes System handelt, hat nichts mit dem execeingebauten System zu tun .
G-Man sagt, dass Monica am
1
Ich habe gerade Ihr Update zu Ihrer Antwort gelesen. (1) Ratet mal was? Wenn die Prozesstabelle voll `which kill`ist, funktioniert die Befehlsersetzung (z. B. ) ebenfalls nicht. (2) Übrigens wird das $(…)Formular über dem `…`Formular empfohlen . (3) Das Erraten des Verzeichnisses ist jedoch ungefährlich. Wenn Sie versehentlich tippen exec /binn/kill, erhalten Sie einfach eine Fehlermeldung und Ihre Shell verschwindet nicht. (4) Aber Sie müssen sich nicht einmal Gedanken darüber machen, in welchem ​​Verzeichnis kill.  execVerwendet wird $PATH, genau wie bei normalen Befehlen. Funktioniert also exec kill …(vorausgesetzt, Sie haben /binin Ihrem Suchpfad).
G-Man sagt, dass Monica am
1
  • Dies ähnelt dem Beispiel von Bruce, bei dem die PID eines Prozesses ermittelt werden muss:

    (cmdpid = $ BASHPID; (sleep 300; kill "$ cmdpid") & exec long-running-befehl )

    in dem du

    1. Starten Sie eine Unterschale (das äußere (und )),
    2. Finden Sie die PID der Unterschale heraus. ( $$Gibt die PID der Haupt-Shell an.)
    3. Trennen Sie eine Sub-Subshell, die Ihren Prozess nach einer Zeitüberschreitung beendet, und
    4. Führen Sie im Verlauf der in Schritt 1 erstellten Subshell einen Befehl aus.

    Dies wird ausgeführt long-running-command, jedoch nur für eine vorher festgelegte, begrenzte Zeitdauer. 

  • Dies ist ein wenig frivol, aber wenn Sie sich entscheiden, für den Rest Ihrer Anmeldesitzung root (oder ein anderer Benutzer) zu sein, können Sie dies tun exec su.

    Eigentlich kann ich mir ein Szenario vorstellen, in dem dies wirklich nützlich wäre. Angenommen, Sie sind bei einem Remote-System angemeldet und aus irgendeinem Grund besteht ein Problem beim Unterbrechen der Verbindung und beim Starten einer neuen Verbindung. Angenommen, das ferne System verfügt über eine Firewall, die einem Zeitplan folgt. Sie durften sich verbinden, als Sie dies taten, und bestehende Verbindungen werden nicht geschlossen, aber zum gegenwärtigen Zeitpunkt werden neue Verbindungen nicht akzeptiert.

    Sie haben getan, was Sie tun wollten, und können sich abmelden. Ihr Freund Bob ist mit Ihnen im Raum und möchte etwas am Remote-System arbeiten - aber er kann keine Verbindung herstellen. Sie geben also ein exec su - bobund übergeben die Workstation an ihn, wenn die Kennwortabfrage angezeigt wird. Es gibt jetzt keinen Prozess mit Ihrer UID (es sei denn, Sie haben etwas im Hintergrund ausgeführt), sodass Bob nicht in der Lage ist, mit Ihren Dateien herumzuspielen. Er wird Ihre Verbindung effektiv übernommen haben (mit Ihrer Zustimmung und Kooperation).

    Anmerkungen:

    • Natürlich funktioniert das nicht, wenn du nicht rennen darfst su.
    • Es wird protokolliert, so dass Sie möglicherweise jemandem Ihre Motive erklären müssen. Da Sie die Richtlinie (den Firewall-Zeitplan) umgehen, können Probleme auftreten.
    • Ich kann nicht garantieren, dass es 100% sicher ist. Zum Beispiel whowird wahrscheinlich immer noch Ihr Name angezeigt. Es ist vorstellbar, dass ein (schlecht geschriebenes) Programm das verwendet, um zu glauben, dass Bob Sie sind, und ihm Zugriff auf Ihre Ressourcen zu gewähren.
    • Wenn das System die Überwachung durchführt, werden die Aktionen von Bob möglicherweise unter Ihrem Namen überprüft.
G-Man sagt, "Monica wiedereinstellen"
quelle
Beachten Sie, dass in der Praxis in den meisten Shells (a;b)bereits das gleiche gilt wie (a;exec b)in Shells, um die Verzweigung für den letzten Befehl in einer Subshell zu optimieren. Die einzigen Ausnahmen zu sein scheinen , bashund mksh. Verwendung exechilft, um es zu garantieren.
Stéphane Chazelas