Betrachten wir für diese Frage ein Bash-Shell-Skript, obwohl diese Frage auf alle Arten von Shell-Skripten anwendbar sein muss.
Wenn jemand ein Shell-Skript ausführt, lädt Linux das gesamte Skript auf einmal (möglicherweise in den Speicher) oder liest es die Skriptbefehle einzeln (Zeile für Zeile)?
Mit anderen Worten, wenn ich ein Shell-Skript ausführe und es lösche, bevor die Ausführung abgeschlossen ist, wird die Ausführung abgebrochen oder wird sie so fortgesetzt, wie sie ist?
linux
shell
shell-script
registrierter Nutzer
quelle
quelle
Antworten:
Wenn Sie verwenden
strace
, können Sie sehen, wie ein Shell-Skript ausgeführt wird, wenn es ausgeführt wird.Beispiel
Angenommen, ich habe dieses Shell-Skript.
Ausführen mit
strace
:Ein Blick in die
strace.log
Datei zeigt Folgendes.Sobald die Datei eingelesen wurde, wird sie ausgeführt:
Oben sehen wir deutlich, dass das gesamte Skript als eine einzige Entität eingelesen und danach ausgeführt wird. So würde es zumindest in Bashs Fall "erscheinen", dass es die Datei einliest und sie dann ausführt. Sie denken also, Sie könnten das Skript bearbeiten, während es ausgeführt wird?
HINWEIS: Tun Sie es jedoch nicht! Lesen Sie weiter, um zu verstehen, warum Sie sich nicht mit einer laufenden Skriptdatei anlegen sollten.
Was ist mit anderen Dolmetschern?
Aber deine Frage ist nicht ganz richtig. Es ist nicht Linux, das notwendigerweise den Inhalt der Datei lädt, sondern der Interpreter, der den Inhalt lädt. Es hängt also wirklich von der Implementierung des Interpreters ab, ob die Datei vollständig oder in Blöcken oder Zeilen gleichzeitig geladen wird.
Warum können wir die Datei nicht bearbeiten?
Wenn Sie jedoch ein viel größeres Skript verwenden, werden Sie feststellen, dass der obige Test etwas irreführend ist. Tatsächlich laden die meisten Interpreter ihre Dateien in Blöcken. Dies ist bei vielen Unix-Tools Standard, bei denen Blöcke einer Datei geladen, verarbeitet und dann ein anderer Block geladen wird. Sie können dieses Verhalten anhand dieser Fragen und Antworten zu U & L sehen, die ich vor einiger Zeit
grep
mit dem Titel geschrieben habe: Wie viel Text verbraucht grep / egrep jedes Mal? .Beispiel
Angenommen, wir erstellen das folgende Shell-Skript.
Ergebnis in dieser Datei:
Welche enthält die folgenden Arten von Inhalten:
Wenn Sie dies mit der gleichen Technik wie oben ausführen, gilt Folgendes
strace
:Sie werden feststellen, dass die Datei in Schritten von 8 KB eingelesen wird, sodass Bash und andere Shells eine Datei wahrscheinlich nicht vollständig laden, sondern in Blöcken einlesen.
Verweise
quelle
Dies ist mehr von der Shell abhängig als vom Betriebssystem.
Abhängig von der Version,
ksh
Lesen Sie das Skript bei Bedarf in 8k- oder 64k-Byte-Blöcken.bash
Lesen Sie das Skript Zeile für Zeile. Angesichts der Tatsache, dass die Zeilen beliebig lang sein können, werden jedes Mal 8176 Bytes ab dem Beginn der nächsten zu analysierenden Zeile gelesen.Dies ist für einfache Konstruktionen, dh eine Reihe von einfachen Befehlen.
Wenn Shell-strukturierte Befehle verwendet werden ( ein Fall, den die akzeptierte Antwort nicht berücksichtigt ), wie eine
for/do/done
Schleife, acase/esac
Schalter, ein Here-Dokument, eine in Klammern gesetzte Subshell, eine Funktionsdefinition usw. und eine beliebige Kombination der oben genannten, werden Shell-Interpreter gelesen Stellen Sie am Ende der Konstruktion zunächst sicher, dass kein Syntaxfehler vorliegt.Dies ist etwas ineffizient, da derselbe Code immer wieder häufig gelesen werden kann, jedoch dadurch gemindert wird, dass dieser Inhalt normalerweise zwischengespeichert wird.
Unabhängig vom Shell-Interpreter ist es sehr unklug, ein Shell-Skript zu ändern, während es ausgeführt wird, da die Shell jeden Teil des Skripts erneut lesen kann. Dies kann zu unerwarteten Syntaxfehlern führen, wenn es nicht synchron ist.
Beachten Sie auch, dass Bash möglicherweise mit einer Segmentierungsverletzung abstürzt, wenn es nicht in der Lage ist, eine zu große Skriptkonstruktion zu speichern. Ksh93 kann fehlerfrei lesen.
quelle
Das hängt davon ab, wie der Interpreter arbeitet, der das Skript ausführt. Der Kernel merkt lediglich, dass die auszuführende Datei mit beginnt
#!
, führt den Rest der Zeile als Programm aus und gibt ihr die ausführbare Datei als Argument. Wenn der dort aufgeführte Interpreter diese Datei zeilenweise liest (wie interaktive Shells es mit Ihrer Eingabe tun), erhalten Sie dies (aber mehrzeilige Schleifenstrukturen werden gelesen und zum Wiederholen beibehalten); Wenn der Interpreter die Datei in den Speicher schlürft, verarbeitet (kompiliert sie möglicherweise zu einer Zwischendarstellung wie Perl und Pyton), wird die Datei vor der Ausführung vollständig gelesen.Wenn Sie die Datei in der Zwischenzeit löschen, wird sie erst gelöscht, wenn der Interpreter sie schließt (wie immer verschwinden Dateien, wenn der letzte Verweis, sei es ein Verzeichniseintrag oder ein Prozess, der sie offen hält).
quelle
Die 'x'-Datei:
Der Lauf:
IIRC Eine Datei wird nicht gelöscht, solange sie von einem Prozess geöffnet bleibt. Durch das Löschen wird nur der angegebene DIRENT entfernt.
quelle