./ vs. zum Ausführen von Programmen unter Terminal

13

Ich brauche eine Klarstellung darüber, wie wir ausführbare Dateien unter dem Terminal ausführen. Dies mag eine lahme Frage sein, aber was ist der Unterschied zwischen dem Ausführen einer ausführbaren Datei mit ./an_executableund . an_executable(nehmen wir an, dass wir uns in dem Verzeichnis befinden, in dem sich eine ausführbare Datei befindet)

Ich weiß bereits, dass erstere die Shell im aktuellen Verzeichnis ( .) nach an_executable suchen lässt , aber warum wird /nachher keine benötigt, .wenn die letztere Version verwendet wird?

Danke im Voraus.

Zip Zap
quelle

Antworten:

22

Die . executableSyntax funktioniert nicht mit jeder ausführbaren Datei (oder?). Stattdessen ist es ein Alias ​​für die sourceeingebaute Bash . Der Unterschied ist also hauptsächlich für Bash-Skripte relevant, und die Wahrheit ist, dass sie völlig verschiedene Dinge sind :)

./executablefragt, ob die ausführbare Datei "normal" ausgeführt werden soll. ./ist ein relativer Verweis auf den aktuellen Pfad. Dadurch wird vermieden, dass die Shell (bash) versucht, die ausführbare Datei in einem Verzeichnis zu finden $PATH(was auch dann der Fall ist, wenn Sie mit dem Befehl keinen Pfad angegeben haben). Der Grund, warum Sie dies nicht einfach tun können, executableliegt in der Sicherheit. Stellen Sie sich vor, Sie dekomprimieren ein Archiv, das Sie heruntergeladen haben, und es enthält eine bösartige Version von ls. Wenn es direkt von Ihrem aktuellen Verzeichnis aus ausgeführt würde, würden Sie diese Version ausführen, ohne es zu merken.

Auf der anderen Seite . executableheißt es "Quelle einer Datei mit dem Namen executable". Da Sie die Datei direkt benennen und es sich nicht unbedingt um eine ausführbare Datei handeln muss, gilt die Sicherheitsbeschränkung für $ PATH nicht. Sourcing wird nur Shell-Skripte "ausführen" (oder anscheinend ausführen). Was es tut, ist:

   source filename [arguments]
          Read and execute commands from filename  in  the  current  shell
          environment  and return the exit status of the last command exe‐
          cuted from filename.

Also ... Was ist wirklich der Unterschied zwischen Executing und Sourcing? Wenn Sie dasselbe Shell-Skript annehmen, wird durch Ausführen von it ( ./script) eine neue Shell erstellt, das Skript in dieser Shell ausgeführt. Wenn das Skript beendet wird, schließen Sie diese Shell und kehren zur übergeordneten Shell zurück. Tatsächlich wird ein neuer bashProzess zum Ausführen des Skripts gestartet .

( . script) bewirkt, dass die aktuelle Shell die Befehle aus der Datei liest, als würden sie in die Befehlszeile eingegeben. Es wurde keine neue Shell erzeugt.

Ein sehr einfacher Weg, um zu sehen, wie sich dies verhält, besteht darin, ein Skript zu schreiben, das nur enthält exit. Wenn Sie ./scriptes tun, scheint nichts zu passieren. Dies liegt daran, dass ein neuer Shell-Prozess gestartet wird, der exitBefehl diese neue Shell beendet und Ihre aktuelle Shell nicht betroffen ist.

Wenn Sie dies tun . script, wird das aktuelle Terminal geschlossen, da der exitBefehl in der aktuellen Shell ausgeführt wird. Das entspricht also der Eingabe exitan der Eingabeaufforderung.

Roadmr
quelle
In der Tat habe ich mich mit Shell-Skripten befasst, als ich dieses Verhalten bemerkte. Vielen Dank, das ist die Antwort, die ich brauchte. :)
zipzap
Eine andere Frage wird gestellt (wenn es Ihnen nichts ausmacht): Wenn mein Skript nur einige einfache Nachrichten mit Echo enthält und ich sie mit ./script ausführe, warum kann ich dann die Nachrichten in der übergeordneten Shell anzeigen, wenn die Subshell geschlossen wird Sobald die Ausführung endet?
zipzap
2
Denn während die Subshell ein separater Prozess ist , verwendet sie dasselbe Terminal wie die aufrufende Shell. Es ist ähnlich, wie Sie die lsAusgabe immer noch sehen können : Sie geben den Befehl ein, er wird ausgeführt, zeigt die Ausgabe an und endet dann, aber die Ausgabe bleibt im Terminal.
Roadmr
2
Shell nicht mit Terminal verwechseln; Sie sind verschiedene Dinge. Öffnen Sie ein Terminal, und die Eingabeaufforderung wird von einer darin ausgeführten bashShell angezeigt . Bei der bashEingabe wird eine andere Shell ausgeführt. Für die erste Shell ist es nur ein auszuführendes Programm. Wenn Sie exitetwas eingeben, schließen Sie die letzte Shell, die Sie gestartet haben, befinden sich aber immer noch in der ersten Shell (diejenige, von der an Sie das Terminal gestartet haben). Auch dies geschieht alles im selben Terminal.
Roadmr
1
@DavidZ Ich habe es erwähnt :) "Sourcing wird nur Shell-Skripte" ausführen "(oder anscheinend ausführen)."
Roadmr