Für ein csh-Skript sollten Sie verwenden #!/bin/csh -f; Das -fweist die Shell an, das .loginund 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 -ffür sh- oder bash-Skripte. es hat nicht die gleiche Bedeutung.
@Kolob Canyon brauchen Sie nicht, aber es kann einigen Editoren bei der Hervorhebung der Syntax helfen (obwohl es normalerweise andere Möglichkeiten gibt, dasselbe zu erreichen): unix.stackexchange.com/a/88730/193985
Braham Snyder
40
Die #!Zeile teilt dem Kernel (insbesondere der Implementierung des execveSystemaufrufs) 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 ./scriptfängt zum Beispiel an, #! /usr/bin/perlals ob die Kommandozeile tatsächlich gewesen wäre
/usr/bin/perl ./script arg1 arg2 arg3
Wie Sie gesehen haben, können Sie #! /bin/shauch ein Skript schreiben, das von interpretiert werden soll sh.
Die #!Zeile wird nur verarbeitet, wenn Sie das Skript direkt aufrufen ( ./scriptin der Befehlszeile). Die Datei muss auch ausführbar sein ( chmod +x script). Wenn Sie dies tun, ist sh ./scriptdie #!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:
Das #!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.
Der Pfad danach #!muss ein absoluter Pfad sein (beginnt mit /). Es darf keine Leerzeichen, Tabulatoren oder Zeilenumbrüche enthalten.
Es ist ein guter Stil, aber nicht erforderlich, ein Leerzeichen zwischen dem #!und dem zu setzen /. Stellen Sie dort nicht mehr als ein Leerzeichen ein.
Sie können keine Shell-Variablen in die #!Zeile einfügen, sie werden nicht erweitert.
Sie können ein Befehlszeilenargument nach dem absoluten Pfad einfügen, das durch ein einzelnes Leerzeichen von diesem getrennt ist. Wie der absolute Pfad darf dieses Argument keine Leerzeichen, Tabulatoren oder Zeilenumbrüche enthalten. Manchmal ist dies notwendig, um Dinge zum Laufen zu bringen ( #! /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.
Einige Leute werden Ihnen sagen , zu verwenden , #! /usr/bin/env interpreterstatt #! /absolute/path/to/interpreter. Dies ist fast immer ein Fehler. Dadurch hängt das Verhalten Ihres Programms von der $PATHVariablen des Benutzers ab, der das Skript aufruft. Und nicht alle Systeme haben envin erster Linie.
Programme, die setuidoder setgidBerechtigungen benötigen, können nicht verwendet werden #!. Sie müssen zu Maschinencode kompiliert werden. (Wenn Sie nicht wissen, was setuidist, machen Sie sich darüber keine Sorgen.)
In Bezug cshdarauf bezieht es sich in shetwa wie Nutrimat Advanced Tea Substitute auf Tee. Es hat (oder hatte eher; moderne Implementierungen shhaben aufgeholt) eine Reihe von Vorteilen gegenüber der shinteraktiven 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 cshVerwandten als Anmeldeshell verwenden, wechseln Sie zu bashoder zsh, damit die interaktive Befehlssprache mit der Skriptsprache übereinstimmt, die Sie lernen.
In neueren Linux-Versionen kann der angegebene Interpreter ein Skript sein. Es ist üblich, das Leerzeichen nach dem wegzulassen #!. 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/envHacks.
Keith Thompson
@KeithThompson Ich habe den Eindruck, dass Linux die einzige gängige Unix-Variante ist, mit der der Interpreter ein Skript sein kann, sodass man sich immer noch nicht darauf verlassen kann. Seit ich das geschrieben habe, bin ich selbst auf eine Situation gestoßen, in #!/usr/bin/envder das Richtige war, aber ich bin weiterhin der Meinung, dass es fast immer eine schlechte Idee ist.
zwol
4
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/cshBezieht sich zB auf die C-Shell, /bin/tcshdie T-Shell, /bin/bashdie 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 chshBefehl ä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 tcshShell 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
Also ist es erforderlich? Woher weiß ich, welche Shell ich wirklich benutze?
Eins Zwei Drei
Wenn ich also die Skripte schreibe, die jemand auf seinem Computer verwenden soll, und ich nicht weiß, welche Shell er verwendet. (Diese Person hat leider keine Ahnung von diesem Zeug, daher kann sie nur das Skript ausführen, ohne etwas zu ändern). Kann ich so etwas machen #! $SHELL? Würde dies die richtige Hülle in den Shebang bringen?
Eins Zwei Drei
1
@OneTwoThree Die meisten Systeme haben die Standard-Shells. Wenn Sie ein Bash- oder Csh-Skript schreiben, sind Sie in Ordnung. Welche Shell sie interaktiv verwenden, spielt keine Rolle, das ist das Schöne an der zB !#/bin/bashRichtlinie. Es teilt dem System mit, welche Shell zum Ausführen Ihres Shell-Skripts verwendet werden soll.
Levon
Der Wert von $SHELLsagt Ihnen nicht unbedingt, welche Shell Sie gerade ausführen. Normalerweise wird Ihnen Ihre Standard- Shell angezeigt . tcsh setzt $versionund $tcsh; Bash-Sets $BASH_VERSION. Nicht alle Schalen haben notwendigerweise ähnliche Mechanismen.
Keith Thompson
1
@OneTwoThree: Die #!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.Antworten:
Dies ist bekannt als
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
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:
quelle
Die
#!
Zeile teilt dem Kernel (insbesondere der Implementierung desexecve
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 Unixen7f 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 neuwo
./script
fängt zum Beispiel an,#! /usr/bin/perl
als ob die Kommandozeile tatsächlich gewesen wäreWie Sie gesehen haben, können Sie
#! /bin/sh
auch ein Skript schreiben, das von interpretiert werden sollsh
.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, istsh ./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. (Dogrep '^#!' /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 habenenv
in erster Linie.setuid
odersetgid
Berechtigungen benötigen, können nicht verwendet werden#!
. Sie müssen zu Maschinencode kompiliert werden. (Wenn Sie nicht wissen, wassetuid
ist, machen Sie sich darüber keine Sorgen.)In Bezug
csh
darauf bezieht es sich insh
etwa wie Nutrimat Advanced Tea Substitute auf Tee. Es hat (oder hatte eher; moderne Implementierungensh
haben aufgeholt) eine Reihe von Vorteilen gegenüber dersh
interaktiven Nutzung, aber die Verwendung (oder dessen Nachkommentcsh
) 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 konzentrierensh
. Wenn Sie einencsh
Verwandten als Anmeldeshell verwenden, wechseln Sie zubash
oderzsh
, damit die interaktive Befehlssprache mit der Skriptsprache übereinstimmt, die Sie lernen.quelle
#!
. 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
Befehl oder alternativ
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
oben in Ihrem Python-Programm
quelle
#! $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 .