Warum beginnen alle Skriptdateien mit?
#!/bin/sh
oder mit
#!/bin/csh
Ist das erforderlich? Was ist der Zweck davon? Und was ist der Unterschied zwischen den beiden?
Warum beginnen alle Skriptdateien mit?
#!/bin/sh
oder mit
#!/bin/csh
Ist das erforderlich? Was ist der Zweck davon? Und was ist der Unterschied zwischen den beiden?
Antworten:
Dies ist bekannt als Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! Interpreter [optional-arg]
Ein Shebang ist nur relevant, wenn ein Skript über die Ausführungsberechtigung verfügt (z. B. chmod u + x script.sh).
Wenn eine Shell das Skript ausführt, wird der angegebene Interpreter verwendet.
Beispiel:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
Die #!
Zeile teilt dem Kernel (insbesondere der Implementierung des execve
Systemaufrufs) mit, dass dieses Programm in einer interpretierten Sprache geschrieben ist. Der folgende absolute Pfadname identifiziert den Interpreter. Zu Maschinencode kompilierte Programme beginnen mit einer anderen Bytesequenz - auf den meisten modernen Unixen 7f 45 4c 46
( ^?ELF), die sie als solche identifiziert.
Sie können jedem Programm nach dem einen absoluten Pfad zuweisen#!
, solange dieses Programm selbst kein #!
Skript ist. Der Kernel schreibt einen Aufruf von neu
./script arg1 arg2 arg3 ...
wo ./script
fängt zum Beispiel an, #! /usr/bin/perl
als ob die Kommandozeile tatsächlich gewesen wäre
/usr/bin/perl ./script arg1 arg2 arg3
Wie Sie gesehen haben, können Sie #! /bin/sh
auch ein Skript schreiben, das von interpretiert werden soll sh
.
Die #!
Zeile wird nur verarbeitet, wenn Sie das Skript direkt aufrufen ( ./script
in der Befehlszeile). Die Datei muss auch ausführbar sein ( chmod +x script
). Wenn Sie dies tun, ist sh ./script
die #!
Zeile nicht erforderlich (und wird ignoriert, falls vorhanden), und die Datei muss nicht ausführbar sein. Der Punkt des Merkmals ist die direkte Eingabe zu ermöglichen invoke interpretiert sprachige Programme , ohne zu wissen , welche Sprache sie geschrieben werden. (Do grep '^#!' /usr/bin/*
- Sie werden feststellen , dass es sehr viele Aktienprogramme in der Tat die Verwendung dieser Funktion.)
Hier sind einige Regeln für die Verwendung dieser Funktion:
#!
müssen die ersten zwei Bytes in der Datei sein. Insbesondere muss die Datei in einer ASCII-kompatiblen Codierung vorliegen (z. B. UTF-8 funktioniert, UTF-16 jedoch nicht) und darf nicht mit einer "Byte-Ordnungsmarke" beginnen, da der Kernel sie sonst nicht als erkennt #!
Skript.#!
muss ein absoluter Pfad sein (beginnt mit /
). Es darf keine Leerzeichen, Tabulatoren oder Zeilenumbrüche enthalten.#!
und dem zu setzen /
. Stellen Sie dort nicht mehr als ein Leerzeichen ein.#!
Zeile einfügen, sie werden nicht erweitert.#! /usr/bin/awk -f
), manchmal ist es nur nützlich ( #! /usr/bin/perl -Tw
). Leider können Sie nicht zwei oder mehr Argumente nach dem absoluten Pfad setzen.#! /usr/bin/env interpreter
statt #! /absolute/path/to/interpreter
. Dies ist fast immer ein Fehler. Dadurch hängt das Verhalten Ihres Programms von der $PATH
Variablen des Benutzers ab, der das Skript aufruft. Und nicht alle Systeme haben env
in erster Linie.setuid
oder setgid
Berechtigungen benötigen, können nicht verwendet werden #!
. Sie müssen zu Maschinencode kompiliert werden. (Wenn Sie nicht wissen, was setuid
ist, machen Sie sich darüber keine Sorgen.)In Bezug csh
darauf bezieht es sich in sh
etwa wie Nutrimat Advanced Tea Substitute auf Tee. Es hat (oder hatte eher; moderne Implementierungen sh
haben aufgeholt) eine Reihe von Vorteilen gegenüber der sh
interaktiven Nutzung, aber die Verwendung (oder dessen Nachkommen tcsh
) für die Skripterstellung ist fast immer ein Fehler . Wenn Sie mit Shell-Skripten im Allgemeinen noch nicht vertraut sind, empfehle ich Ihnen dringend, sie zu ignorieren und sich darauf zu konzentrieren sh
. Wenn Sie einen csh
Verwandten als Anmeldeshell verwenden, wechseln Sie zu bash
oder zsh
, damit die interaktive Befehlssprache mit der Skriptsprache übereinstimmt, die Sie lernen.
#!
. Kein Kommentar dazu, ob das ein guter Stil ist. In dieser Frage und meiner Antwort finden Sie eine Diskussion über die Vor- und Nachteile des #!/usr/bin/env
Hacks.
#!/usr/bin/env
der das Richtige war, aber ich bin weiterhin der Meinung, dass es fast immer eine schlechte Idee ist.
Dies definiert, welche Shell (Befehlsinterpreter) Sie zum Interpretieren / Ausführen Ihres Skripts verwenden. Jede Shell unterscheidet sich geringfügig in der Art und Weise, wie sie mit dem Benutzer interagiert und Skripte (Programme) ausführt.
Wenn Sie an der Unix-Eingabeaufforderung einen Befehl eingeben, interagieren Sie mit der Shell.
#!/bin/csh
Bezieht sich zB auf die C-Shell, /bin/tcsh
die T-Shell, /bin/bash
die Bash-Shell usw.
Sie können erkennen, welche interaktive Shell Sie verwenden
echo $SHELL
Befehl oder alternativ
env | grep -i shell
Sie können Ihre Befehlsshell mit dem chsh
Befehl ändern .
Jedes hat einen etwas anderen Befehlssatz und eine andere Art der Zuweisung von Variablen sowie einen eigenen Satz von Programmierkonstrukten. Zum Beispiel sieht die if-else-Anweisung mit bash anders aus als die in der C-Shell.
Diese Seite könnte von Interesse sein, da sie zwischen bash- und tcsh-Befehlen / -Syntax "übersetzt".
Mit der Direktive im Shell-Skript können Sie Programme mit einer anderen Shell ausführen. Zum Beispiel benutze ich die tcsh
Shell interaktiv, führe aber häufig Bash-Skripte mit / bin / bash in der Skriptdatei aus.
Beiseite:
Dieses Konzept erstreckt sich auch auf andere Skripte. Wenn Sie beispielsweise in Python programmieren, würden Sie setzen
#!/usr/bin/python
oben in Ihrem Python-Programm
#! $SHELL
? Würde dies die richtige Hülle in den Shebang bringen?
!#/bin/bash
Richtlinie. Es teilt dem System mit, welche Shell zum Ausführen Ihres Shell-Skripts verwendet werden soll.
$SHELL
sagt Ihnen nicht unbedingt, welche Shell Sie gerade ausführen. Normalerweise wird Ihnen Ihre Standard- Shell angezeigt . tcsh setzt $version
und $tcsh
; Bash-Sets $BASH_VERSION
. Nicht alle Schalen haben notwendigerweise ähnliche Mechanismen.
#!
Zeile muss mit der Syntax des Skripts übereinstimmen, nicht mit der interaktiven Shell, die von demjenigen verwendet wird, der das Skript ausführt .
#!/bin/csh -f
; Das-f
weist die Shell an, das.login
und nicht des Benutzers zu verwenden.cshrc
, wodurch das Skript schneller ausgeführt wird und Abhängigkeiten vom Setup des Benutzers vermieden werden. (Oder noch besser, schreiben Sie keine csh-Skripte.) Verwenden Sie sie nicht-f
für sh- oder bash-Skripte. es hat nicht die gleiche Bedeutung.