wake-up-neo.net

Soll ich einen Shebang mit Bash-Skripten verwenden?

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
27
Steven Penny

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.

40
Roland Smith

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.

13
Barmar

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

3
jrjc
  • 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:

So wie es aussieht, darf eine streng konforme Anwendung kein "#" verwenden. als die ersten beiden Zeichen der Datei.

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.

3
jlliagre

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 ...

1
pyrrhic

$ 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

0
Chirality

Zusätzlich zu dem, was die anderen sagten, ermöglicht der Shebang in einigen Texteditoren auch die Syntaxhervorhebung, zum Beispiel vim.

0
Konrad Höffner