GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was genau passiert, wenn ich eine Datei in der Shell ausführe?

Ich dachte also, ich hätte ein gutes Verständnis davon, aber ich habe gerade einen Test durchgeführt (als Antwort auf ein Gespräch, in dem ich mit jemandem nicht einverstanden war) und festgestellt, dass mein Verständnis fehlerhaft ist …

So detailliert wie möglich Was genau passiert, wenn ich eine Datei in meiner Shell ausführe? Was ich meine ist, wenn ich Folgendes eingebe:./somefile some arguments in meine Shell und drücken Sie die Eingabetaste (und somefile existiert in cwd, und ich habe Lese- und Ausführungsberechtigungen für somefile ) was passiert dann unter der Haube?

Ich dachte Die Antwort war:

  1. Die Shell führt einen Syscall zu exec durch , wobei der Pfad zu somefile übergeben wird
  2. Der Kernel untersucht somefile und sieht sich die magische Nummer der Datei an, um festzustellen, ob es sich um ein Format handelt, das der Prozessor verarbeiten kann
  3. Wenn die magische Zahl anzeigt, dass die Datei in einem Format vorliegt, das der Prozessor ausführen kann, dann
    1. ein neuer Prozess wird erstellt (mit einem Eintrag in der Prozesstabelle)
    2. somefile wird gelesen/auf den Speicher abgebildet. Ein Stack wird erstellt und die Ausführung springt zum Einstiegspunkt des Codes von somefile , mit ARGV mit einem Array der Parameter initialisiert (ein char** , ["some","arguments"] )
  4. Wenn die magische Zahl ein Shebang ist, dann exec() erzeugt einen neuen Prozess wie oben, aber die verwendete ausführbare Datei ist der Interpreter, auf den der Shebang verweist (z. B. /bin/bash oder /bin/perl ) und somefile wird an STDIN übergeben
  5. Wenn die Datei keine gültige magische Nummer hat, tritt ein Fehler wie „ungültige Datei (schlechte magische Nummer):Exec-Formatfehler“ auf

Jemand sagte mir jedoch, dass, wenn die Datei aus reinem Text besteht, die Shell versucht, die Befehle auszuführen (als ob ich bash somefile eingegeben hätte ). Ich habe es nicht geglaubt, aber ich habe es einfach versucht, und es war richtig. Ich habe also eindeutig einige Missverständnisse darüber, was hier tatsächlich passiert, und würde gerne die Mechanik verstehen.

Was genau passiert, wenn ich eine Datei in meiner Shell ausführe? (so detailliert wie möglich…)

Akzeptierte Antwort:

Die endgültige Antwort auf „Wie Programme ausgeführt werden“ unter Linux ist das Artikelpaar auf LWN.net mit den überraschenderweise betitelten „Wie Programme ausgeführt werden“ und „Wie Programme ausgeführt werden:ELF-Binärdateien“. Der erste Artikel befasst sich kurz mit Skripten. (Genau genommen liegt die endgültige Antwort im Quellcode, aber diese Artikel sind einfacher zu lesen und enthalten Links zum Quellcode.)

Ein wenig Experimentieren zeigt, dass Sie es ziemlich richtig gemacht haben und dass die Ausführung einer Datei, die eine einfache Liste von Befehlen enthält, ohne einen Kram von der Shell gehandhabt werden muss. Die Manpage execve(2) enthält Quellcode für ein Testprogramm, execve; Wir werden das verwenden, um zu sehen, was ohne Shell passiert. Schreiben Sie zuerst ein Testskript, testscr1 , enthält

#!/bin/sh

pstree

und ein weiterer, testscr2 , die nur

enthält
pstree

Machen Sie beide ausführbar und vergewissern Sie sich, dass sie beide von einer Shell ausgeführt werden:

chmod u+x testscr[12]
./testscr1 | less
./testscr2 | less

Versuchen Sie es jetzt erneut mit execve (vorausgesetzt, Sie haben es im aktuellen Verzeichnis erstellt):

./execve ./testscr1
./execve ./testscr2

testscr1 läuft noch, aber testscr2 produziert

execve: Exec format error

Dies zeigt, dass die Shell testscr2 handhabt anders. Es verarbeitet jedoch nicht das Skript selbst, sondern verwendet weiterhin /bin/sh das zu tun; Dies kann durch Weiterleiten von testscr2 überprüft werden zu less :

./testscr2 | less -ppstree

Auf meinem System bekomme ich

    |-gnome-terminal--+-4*[zsh]
    |                 |-zsh-+-less
    |                 |     `-sh---pstree

Wie Sie sehen können, gibt es die Shell, die ich verwendet habe, zsh , die less gestartet hat , und eine zweite Shell, einfach sh (dash auf meinem System), um das Skript auszuführen, das pstree ausgeführt hat . In zsh Dies wird von zexecve gehandhabt in Src/exec.c :Die Shell verwendet execve(2) um zu versuchen, den Befehl auszuführen, und wenn das fehlschlägt, liest es die Datei, um zu sehen, ob sie einen Shebang hat, verarbeitet es entsprechend (was der Kernel auch getan haben wird), und wenn das fehlschlägt, versucht es, die Datei mit sh , solange es kein Nullbyte aus der Datei gelesen hat:

        for (t0 = 0; t0 != ct; t0++)
            if (!execvebuf[t0])
                break;
        if (t0 == ct) {
            argv[-1] = "sh";
            winch_unblock();
            execve("/bin/sh", argv - 1, newenvp);
        }

bash hat das gleiche Verhalten, implementiert in execute_cmd.c mit einem hilfreichen Kommentar (wie von taliezin hervorgehoben):

Führen Sie einen einfachen Befehl aus, der hoffentlich irgendwo in einer Plattendatei
definiert ist.

  1. fork ()
  2. Rohre verbinden
  3. Befehl nachschlagen
  4. Weiterleitungen durchführen
  5. execve ()
  6. Falls die execve fehlgeschlagen ist, überprüfen Sie, ob für die Datei der Ausführungsmodus eingestellt ist.
    Wenn dies der Fall ist und es sich nicht um ein Verzeichnis handelt, führen Sie dessen Inhalt als
    Shell-Skript aus.

POSIX definiert eine Reihe von Funktionen, die als exec(3) bekannt sind Funktionen, die execve(2) umschließen und bieten diese Funktionalität auch an; Einzelheiten finden Sie in der Antwort von Muru. Zumindest unter Linux werden diese Funktionen von der C-Bibliothek implementiert, nicht vom Kernel.

Verwandte:Der Zweck des Schlüsselworts „do“ in Bash für Schleifen?
Linux
  1. Was ist der Zweck der .bashrc-Datei in Linux

  2. Was passiert mit einem geöffneten Datei-Handle unter Linux, wenn die angegebene Datei verschoben oder gelöscht wird

  3. Wie verwendet man inotify richtig?

  4. Was bewirkt die Ausführungserlaubnis?

  5. Was genau bestimmt, ob ein Hintergrundjob beendet wird, wenn die Shell beendet wird, oder ob er beendet wird?

Was ist die Shell unter Linux?

Wie führe ich eine .sh-Datei aus, wenn die Sitzung beginnt?

Was im Hintergrund passiert, wenn Sie unter Linux den Befehl „useradd“ ausführen

Was ist eine .sh-Datei?

Was passiert, wenn eine Datei, die zu 100 % in den Seitencache eingelagert ist, von einem anderen Prozess geändert wird

Was ist die Standard-Shell von Busybox?