Ich benutze Bash
$ echo $Shell
/bin/bash
und seit ungefähr einem Jahr habe ich aufgehört, Shebangs mit meinen Bash-Skripts zu verwenden. Kann Ich profitiere von der Verwendung von #!/bin/sh
oder #!/bin/bash
?
Update: In bestimmten Situationen wird eine Datei nur mit dem Beispiel Shebang als Skript behandelt
$ cat foo.sh
ls
$ cat bar.sh
#!/bin/sh
ls
$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX Shell script, ASCII text executable
Auf UNIX-ähnlichen Systemen sollten Sie Skripte immer mit einer Shebang-Zeile starten. Der Systemaufruf execve
(der für das Starten von Programmen verantwortlich ist) basiert auf einer ausführbaren Datei mit einem ausführbaren Header oder einer Shebang-Zeile .
Aus FreeBSDs Manpage ausführen :
The execve() system call transforms the calling process into a new process. The new process is constructed from an ordinary file, whose name is pointed to by path, called the new process file. [...] This file is either an executable object file, or a file of data for an interpreter. [...] An interpreter file begins with a line of the form: #! interpreter [arg] When an interpreter file is execve'd, the system actually execve's the specified interpreter. If the optional arg is specified, it becomes the first argument to the interpreter, and the name of the originally execve'd file becomes the second argument
Ähnlich aus der Linux-Handbuchseite :
execve () führt das Programm aus, auf das der Dateiname verweist. Dateiname muss entweder eine ausführbare Binärdatei oder ein Skript sein, das mit einer Zeile der folgenden Form beginnt:
#! interpreter [optional-arg]
In der Tat, wenn eine Datei nicht die richtige "magische Nummer" im Header hat (wie ein ELF-Header oder #!
), Wird execve
Fehler mit dem ENOEXEC-Fehler (erneut aus der ausführbaren FreeBSD-Manpage):
[ENOEXEC] Die neue Prozessdatei verfügt über die entsprechende Zugriffsberechtigung, hat jedoch eine ungültige magische Nummer im Header.
Wenn die Datei über ausführbare Berechtigungen verfügt, aber keine Shebang-Zeile, sondern eine Textdatei zu sein scheint, hängt das Verhalten von der Shell ab, in der Sie ausgeführt werden.
Die meisten Shells scheinen eine neue Instanz von sich selbst zu starten und füttern die Datei, siehe unten.
Da es keine Garantie gibt, dass das Skript tatsächlich für diese Shell geschrieben wurde, kann dies funktionieren oder auf spektakuläre Weise fehlschlagen.
From tcsh (1) :
On systems which do not understand the `#!' script interpreter conven‐ tion the Shell may be compiled to emulate it; see the version Shell variable. If so, the Shell checks the first line of the file to see if it is of the form `#!interpreter arg ...'. If it is, the Shell starts interpreter with the given args and feeds the file to it on standard input.
Aus FreeBSDs sh (1) :
If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the Shell will run a new instance of sh to interpret it.
Aus Bash (1):
If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a Shell script, a file containing Shell commands. A subshell is spawned to execute it.
Sie können sich nicht immer auf den Speicherort eines nicht standardmäßigen Programms wie bash verlassen. Ich habe Bash in /usr/bin
, /usr/local/bin
, /opt/fsf/bin
Und /opt/gnu/bin
Gesehen, um nur einige zu nennen.
Daher ist es im Allgemeinen eine gute Idee, env
zu verwenden.
#!/usr/bin/env bash
Wenn Sie möchten, dass Ihr Skript portierbar ist, verwenden Sie sh
anstelle von bash
.
#!/bin/sh
Während Standards wie POSIX nicht die absoluten Pfade von Standarddienstprogrammen garantieren , scheinen die meisten UNIX-ähnlichen Systeme sh
in /bin
Und env
in /usr/bin
.
Skripte sollten immer mit einer Shebang-Zeile beginnen. Wenn ein Skript nicht damit beginnt, kann es von der aktuellen Shell ausgeführt werden. Das bedeutet jedoch, dass sich das Skript möglicherweise anders verhält, wenn jemand, der Ihr Skript verwendet, eine andere Shell ausführt als Sie. Dies bedeutet auch, dass das Skript nicht direkt von einem Programm aus ausgeführt werden kann (z. B. der Systemaufruf C exec()
oder find -exec
). Es muss von einer Shell aus ausgeführt werden.
Vielleicht interessiert Sie eine frühe Beschreibung von Dennis M Ritchie (dmr
), der den #!
erfunden hat:
Von uucp Do Jan 10 01:37:58 1980
Von dmr Do Jan 10 04:25:49 1980 von der Forschung entfernt
Das System wurde so geändert, dass wenn eine Datei ausgeführt werden beginnt mit den magischen Zeichen #! , der Rest des Zeile ist der Name eines Interpreters für die ausgeführten Datei. Früher (und auch heute noch) hat die Shell einen großen Teil dieser Arbeit erledigt; es hat sich automatisch in einer Textdatei mit dem ausführbaren Modus ausgeführt wenn der Name der Textdatei als Befehl eingegeben wurde. Einrichtung der Einrichtung in das System bietet die folgenden Vorteile.
1) Es macht Shell-Skripte mehr wie echte ausführbare Dateien, weil Sie können das Thema "Exec" sein.
2) Wenn Sie ein 'ps' ausführen, während ein solcher Befehl ausgeführt wird, ist dessen realer Name erscheint anstelle von 'sh'. Ebenso erfolgt die Abrechnung auf Basis von der richtige Name.
3) Shell-Skripte können Set-User-ID sein.
4) Es ist einfacher alternative Schalen zur Verfügung zu haben; z.B. wenn du möchtest Beim Berkeley-Csh gibt es keine Frage, welche Shell eine Datei interpretieren.
5) Andere Dolmetscher können sich dadurch leichter einfügen.
Um diese wunderbare Gelegenheit zu nutzen, setzen Sie
#! /bin/sh
am linken Rand der ersten Zeile Ihrer Shell-Skripte. Leerzeichen nach dem ! Ist ok. Verwenden Sie einen vollständigen Pfadnamen (es wird keine Suche durchgeführt). Bei der Momentan ist die gesamte Zeile auf 16 Zeichen beschränkt, aber diese Begrenzung wird erhöht werden.
Hoffe das hilft
Wenn Sie bash -Skripte schreiben, d. H. Nicht portierbare Skripts, die Bashisms enthalten, sollten Sie weiterhin #!/bin/bash
Shebang verwenden, um sicherzustellen, dass der richtige Interpreter verwendet wird. Sie sollten Shebang nicht durch #!/bin/sh
ersetzen, da bash im POSIX-Modus ausgeführt wird, sodass sich einige Ihrer Skripts möglicherweise anders verhalten.
Wenn Sie portable - Skripts schreiben, d. H. Nur mit POSIX-Dienstprogrammen und deren unterstützten Optionen, verwenden Sie #!/bin/sh
möglicherweise weiterhin auf Ihrem-System (d. H. Eines, bei dem /bin/sh
eine POSIX-Shell ist).
Wenn Sie strikt konforme POSIX-Skripts schreiben, die auf verschiedenen Plattformen verteilt werden sollen, und Sie sind sicher, dass sie nur von einem POSIX-konformen System aus gestartet werden, sollten Sie und sollten das Shebang wie im POSIX-Standard angegeben entfernen:
Der Grund dafür ist, dass der POSIX-Standard nicht /bin/sh
die POSIX-kompatible Shell verlangt. Es gibt also keine tragbare Möglichkeit, den Pfad in einem Shebang anzugeben. In diesem dritten Fall können Sie den Interpreter einfach im find-Befehl selbst angeben, um die 'find -exec'-Syntax auf Systemen verwenden zu können, die kein Shebangless-Skript ausführen können, das noch ausgeführt werden kann.
find /tmp -name "*.foo" -exec sh -c 'myscript "[email protected]"' sh {} +
Da hier sh
ohne Pfad angegeben wird, wird die POSIX-Shell ausgeführt.
Der Header ist nützlich, da er angibt, welche Shell beim Ausführen des Skripts verwendet werden soll. Zum Beispiel würde #!/bin/zsh
die Shell in zsh anstelle von bash ändern, wo Sie verschiedene Befehle verwenden können.
Zum Beispiel diese Seite gibt Folgendes an:
Verwenden Sie #!/Bin/sh, die Standard-Bourne-Shell in den meisten kommerziellen Varianten von UNIX macht das Skript auf Nicht-Linux-Maschinen portierbar, obwohl Sie opfere Bash-spezifische Funktionen ...
$ Shell und #!/Bin/bash oder #!/Bin/sh unterscheiden sich.
Zum Start ist #!/Bin/sh auf den meisten Linux-Systemen ein Symlink zu/bin/bash (unter Ubuntu heißt es jetzt/bin/dash)
Aber ob Sie mit/bin/sh oder/bin/bash beginnen:
Bash und Sh sind zwei verschiedene Schalen. Bash ist im Grunde sh, mit mehr Funktionen und eine bessere Syntax. Die meisten Befehle funktionieren gleich, sind jedoch anders.
Nehmen Sie einfach an, wenn Sie ein Bash-Skript schreiben, bleiben Sie bei/bin/bash und nicht bei/sh, da Probleme auftreten können.
$ Shell spiegelt nicht notwendigerweise die aktuell laufende Shell wider. Stattdessen ist $ Shell die vom Benutzer bevorzugte Shell, normalerweise die ein Satz in/etc/passwd. Wenn Sie nach der Protokollierung eine andere Shell starten, __. In können Sie nicht unbedingt erwarten, dass $ Shell mit der aktuellen Shell .__ übereinstimmt. nicht mehr.
Dies ist beispielsweise mein, aber es könnte auch/root:/bin/dash oder/root:/bin/sh sein, abhängig davon, welche Shell Sie in passwd eingegeben haben. Um Probleme zu vermeiden, sollten Sie die passwd-Datei unter/bin/bash aufbewahren und dann $ Shell vs. #!/Bin/bash verwenden.
[email protected]:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
Quellen: http://Shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash/https: //unix.stackexchange. de/questions/43499/Unterschied zwischen Echo-Shell-and-which-bashhttp://man.cx/shhttp://man.cx/ bash
Zusätzlich zu dem, was die anderen sagten, ermöglicht der Shebang in einigen Texteditoren auch die Syntaxhervorhebung, zum Beispiel vim.