Warum muss ich sh setzen, bevor .sh-Dateien ausgeführt werden?

16

Wenn ich .shDateien in Terminal ausführen möchte , muss ich sie voranstellen sh.

Gibt es eine Möglichkeit, dies zu vermeiden und so das Tippen zu sparen?

Mehr als fünf
quelle
3
Ich habe einen Ordner unter ~ / bin erstellt, in den ich meine Shell-Skripte einfügen und auf meinem $ PATH ablegen kann. Außerdem habe ich dem Ordner ~ / bin eine Ordneraktion angehängt, um die Ausführungsberechtigungen automatisch festzulegen, da dies so einfach zu vergessen ist.
Kaydell

Antworten:

22

Wenn Sie Ihr Skript über die Shell ausführen, benötigen Sie das #!/bin/shin dieser Antwort beschriebene " shebang" nicht. Jedes von mir verwendete Unix-ähnliche System, einschließlich OS X, wird standardmäßig verwendet, /bin/shwenn kein spezifischer Interpreter angegeben ist ( obwohl es eine gute Idee ist, da Nicht-Shells nicht wissen, wie sie Ihr Skript ausführen sollen, wenn Sie nicht den Shebang geben.)

Sie brauchen auch keine .shErweiterung. Sie tun müssen ausführbare Berechtigungen festlegen, zB

$ chmod +x script.sh

( $Dies ist die Shell-Eingabeaufforderung. Ich verwende sie, um Befehle zu veranschaulichen, die Sie der interaktiven Shell geben. Geben Sie sie nicht ein!)

Ich glaube jedoch, Sie sind verwirrt, dass Sie ein Skript erstellt haben, z. B. script.shim aktuellen Verzeichnis, und versuchen, es durch einfaches Eingeben auszuführen script.sh. z.B

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^DMittel control- D. Sie werden diese Notation in vielen writeups zu finden unter Unix verwenden.)

Die Tatsache, dass es sich script.shin diesem Fall um ein Shell-Skript handelt, ist nur das halbe Problem. Ihr eigentliches Problem ist, dass die Shell standardmäßig nicht das aktuelle Verzeichnis nach einem Programm durchsucht. Dies funktioniert jedoch:

$ sh script.sh
hello, world

weil shdas Skript als Argument nimmt.

Sie können ein Skript - oder auch eine beliebige ausführbare Datei - im aktuellen Verzeichnis ausführen , wenn es als ausführbar markiert ist (z. B. chmod +x), indem Sie angeben, dass Sie das Skript im aktuellen Verzeichnis ausführen möchten:

$ ./script.sh
hello, world

Sie können das Skript auch in ein Verzeichnis auf Ihrer Website verschieben PATH. Ich empfehle /usr/local/bindies, wenn Ihr Skript systemweit verwendet werden soll, oder ein binVerzeichnis in Ihrem Zuhause, wenn das Skript nur für Sie bestimmt ist. Letzteres erfordert, dass Sie die folgenden Zeilen zu Ihrem Ausgangsverzeichnis hinzufügen $HOME/bin, die sich in Ihrem neuen bin-Verzeichnis befinden:PATH.profile

PATH=$HOME/bin:$PATH
export PATH

Schließlich können Sie, wenn Sie möchten, das aktuelle Verzeichnis zu Ihrem hinzufügen PATH, wodurch Sie einfach zu einem Verzeichnis script.shwechseln können, das - oder eine andere ausführbare Datei - enthält, und es eingeben können

$ script.sh

um es auszuführen. Doch ich diese Praxis nicht empfehlen , da ein Angreifer nun Sie in Laufen eine beliebige ausführbare Datei durch Fallenlassen ein ausführbares Skript (namens, sagen wir, Trick kann ls) in ein Verzeichnis wird in Ihnen. Wenn Sie wirklich es tun wollen, obwohl, Fügen Sie einfach Folgendes hinzu .profile:

PATH=.:$PATH
export PATH
Zickzack
quelle
Lege das '.' am ende des $ PATH statt am anfang und jetzt brauchen sie sich keine sorgen mehr um ein phantom 'ls' zu machen. (Obwohl, wenn jemand in Ihr System eindringen kann, haben Sie größere Probleme.)
TJ Luoma
2
@TJ, aber Sie haben über Dinge zu kümmern , wie sloder llsoder l... dh Tippfehler. Lass einfach .aus $PATH. Außerdem können (oder sollten) Sie möglicherweise nicht jedem auf Ihrem System vertrauen. Angenommen, es gibt einige Exploit, der es einem Angreifer ermöglicht , eine beliebige Datei in ein Verzeichnis zu löschen, aber sie müssen Sie die Datei auszuführen , um zu einem besseren eskalieren ausnutzen (zB, Daten sammeln und nach Hause telefonieren). Verteidigung in der Tiefe!
Reid
@TJLuoma Was @Reid gesagt hat, und denken Sie daran, dass es viele Anwendungsfälle für ein Unix-System gibt, die über einen persönlichen OS X-Desktop hinausgehen. Ich habe es noch nicht ausprobiert, aber ich wette, dass sogar das Gastkonto eines dieser Elemente in /tmpeinem anderen von der Welt beschreibbaren Verzeichnis belassen könnte.
Zigg
Wenn Sie ein System verwenden, auf dem andere Benutzer Zugriff auf die von Ihnen verwendeten Verzeichnisse haben, treten größere Probleme auf.
TJ Luoma
@TJLuoma Sie sollten also auf keinem Unix-System mehrere Konten verwenden. /tmpet al. Komm mit dem Territorium.
Zigg
10

Sie müssen nicht aufrufen, shwenn die Skriptdatei als ausführbar markiert ist. In diesem Fall können Sie meinen Namen so nennen, wie Sie es mit jedem anderen Befehl aus der vorhandenen Shell tun würden.


Um richtig zu sein, müssen Sie zwei Dinge tun:

  1. Bearbeiten Sie Ihr Skript so, dass oben in Ihrem Skript eine shebang- Direktive steht:

    #!/bin/sh

    ... Das würde der Shell mitteilen, welcher Interpreter zum Ausführen des Skripts verwendet werden soll. in diesem Fall die /bin/shausführbare Datei.

  2. Markieren Sie das Skript mit dem Befehl chmod als von Ihnen ausführbar :

    chmod u+x scriptname.sh

Sobald Sie beides getan haben, sollten Sie in der Lage sein, Ihr Skript auszuführen, indem Sie den Dateinamen Ihres Skripts in die Befehlszeile eingeben. Sie müssen sich im selben Verzeichnis wie Ihr Skript befinden, es sei denn, Sie führen den hinzugefügten Schritt des Hinzufügens des enthaltenen Ordners zu Ihrer PATH-Variablen aus . Wenn es Ihnen egal ist, auf welcher Shell das Skript ausgeführt wird, müssen Sie den ersten Schritt nicht angeben. shOft ist es jedoch besser, genau zu sein und "shebangsh" festzulegen.

Chris W. Rea
quelle
Shebangs sind eigentlich nicht nötig /bin/sh, obwohl sie nicht weh tun.
Zigg
@zigg - Du hast recht. Ich hoffe , dass Chris nicht meine Änderungen hat nichts dagegen ... Nuke oder Re-Editierung , wie gewünscht: -0
bmike
@bmike Die Änderungen funktionieren für mich. Was die Shebangs angeht, war es meine Gewohnheit, immer genau anzugeben, da ich zu kshmeiner Zeit viele Skripte auf HP-UX geschrieben habe - aber es ist gut zu wissen, dass dies nicht unbedingt erforderlich ist.
Chris W. Rea
1
Ich denke, ich muss mich von meiner früheren Aussage zur Shebang-Notwendigkeit zurückziehen (obwohl der Rest meiner Antwort immer noch gültig ist.) Sie können ein Shebang-freies Skript von einer Shell aus ausführen, aber wenn Sie einen execSyscall verwenden, erhalten Sie ENOEXEC(Exec-Format-Fehler) ). Entschuldigung, @bmike, @ ChrisW.Rea. Ich werde jetzt meine Antwort bearbeiten.
Zigg