Должен ли я использовать Shebang со сценариями Bash?

Я использую Bash

$ echo $SHELL
/bin/bash

и примерно год назад я перестал использовать Shebangs с моими сценариями Bash. Мочь Я пользуюсь#!/bin/sh или #!/bin/bash?

Update: в некоторых ситуациях файл рассматривается только как скрипт с Пример притон,

$ 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

7 ответов


в UNIX-подобных системах вы должны всегда запуск скриптов с линией shebang. Системный вызов execve (который отвечает за запуск программ) использует на исполняемом файле, имеющем либо исполняемый заголовок, либо строку shebang.

из FreeBSD руководство execve:

 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

аналогично с страница руководства Linux:

вызова execve() выполняет программа указала на имя файла. имя файла должно быть либо двоичный исполняемый файл, либо скрипт, начинающийся со строки форма:

#! interpreter [optional-arg]

фактически, если файл не имеет правильного "магического числа" в его заголовке (например, заголовок ELF или #!),execve будет не с ошибкой ENOEXEC (опять же из manpage execve FreeBSD):

[ENOEXEC] новый файл процесса имеет соответствующий доступ разрешение, но имеет недопустимое магическое число в заголовок.


если файл имеет исполняемые разрешения, но нет строки shebang, но кажется текстовым файлом, поведение зависит от оболочки, в которой вы работаете.

большинство оболочек, похоже, запускают новый экземпляр себя и подают ему файл, см. ниже.

поскольку нет никакой гарантии, что сценарий был фактически написан для этой оболочки, это может работать или терпеть неудачу эффектно.

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

из FreeBSD 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.

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

вы не можете всегда зависеть от местоположения нестандартной программы, такой как bash. Я видел баш в /usr/bin, /usr/local/bin, /opt/fsf/bin и /opt/gnu/bin чтобы назвать несколько.

так что, как правило, хорошая идея использовать env;

#!/usr/bin/env bash

если вы хотите, чтобы ваш скрипт был портативным, используйте sh вместо bash.

#!/bin/sh

в то время как стандарты, такие как POSIX do не гарантия абсолютные пути стандартных утилит, большинство UNIX-подобных систем, похоже, имеют sh на /bin и env на /usr/bin.


Скрипты всегда должны начинаться с строки shebang. Если скрипт не запускается с этого, то он может быть выполнен текущей оболочкой. Но это означает, что если кто-то, кто использует ваш сценарий, работает в другой оболочке, чем вы, сценарий может вести себя по-другому. Кроме того, это означает, что скрипт не может быть запущен непосредственно из программы (например, с exec() системный вызов, или find -exec), он должен быть запущен из командной строки.


вас может заинтересовать раннее описание Деннис м Ритчи (dmr), который изобрел #! :

из uucp чт 10 января 01:37: 58 1980

.>Из ДМР чт 10 января 04: 25: 49 1980 удален от исследований

система была изменена так, что если файл выполнение начинается с волшебных символов #! остальные строка понимается как имя интерпретатора для выполняемого файл. Ранее (и на самом деле до сих пор) оболочка сделала большую часть этой работы; он автоматически выполнялся в текстовом файле с исполняемым режимом когда имя текстового файла было введено как команда. Установка объекта система дает следующие преимущества.

1) это делает сценарии оболочки больше похожими на реальные исполняемые файлы, потому что они могут быть предметом ' exec.'

2) Если вы делаете " ps " во время выполнения такой команды, ее реальное имя появится вместо "ш". Аналогичным образом, учет осуществляется на основе настоящее имя.

3) сценарии оболочки могут быть установлены-user-ID.

4) проще иметь альтернативные оболочки; например, если вам нравится в Berkeley csh нет вопроса о том, какая оболочка должна интерпретировать файл.

5) это позволит другим переводчикам вписаться более плавно.

чтобы воспользоваться этой замечательной возможностью, положите

   #! /bin/sh

слева поле первой строки скриптов оболочки. Холостые патроны после ! ОК. Используйте полный путь (поиск не выполняется). В момент вся строка ограничена 16 символами, но это ограничение будет поднят.

надеюсь, что это помогает


  • если вы пишите Баш скрипты, т. е. не портативный скриптов, содержащих bashisms, вы должны продолжать использовать #!/bin/bash shebang, чтобы убедиться, что используется правильный интерпретатор. Вы не должны заменять shebang на #!/bin/sh as bash будет работать в режиме POSIX, поэтому некоторые из ваших скриптов могут вести себя по-разному.

  • если вы пишите портативный скрипты, т. е. скрипты, использующие только утилиты POSIX и поддерживаемые ими параметры, вы может продолжать использовать #!/bin/sh on код система (т. е. тот, где /bin/sh является оболочкой POSIX).

  • это вы пишите строго соответствующие скрипты POSIX для распространения на различных платформах, и вы уверены, что они будут запущены только из системы, соответствующей POSIX, вы можете и, вероятно, должны удалить shebang, как указано в стандарте POSIX:

как оно стоит, строго соответствуя применение должно не использовать"#!- как первые два символа файла.

обоснование в стандарте POSIX не определяет /bin/sh быть совместимой с POSIX оболочкой, поэтому нет портативного способа указать ее путь в shebang. В этом третьем случае, чтобы иметь возможность использовать синтаксис "find-exec" в системах, не способных запустить shebangless все еще исполняемый скрипт, вы можете просто указать интерпретатор в самой команде find, например:

find /tmp -name "*.foo" -exec sh -c 'myscript "$@"' sh {} + 

здесь, как это без пути будет запущена оболочка POSIX.


заголовок полезен, так как он указывает, какую оболочку использовать при запуске скрипта. Например, #!/bin/zsh изменил бы оболочку на zsh вместо bash, где вы можете использовать разные команды.

например, на этой странице указывает следующее:

использование #!/bin/ sh, оболочка Bourne по умолчанию в большинстве коммерческих вариантов UNIX, делает скрипт переносимым на не-Linux машины, хотя вы жертвоприношение Bash-особенности ...


$ SHELL и #!как /bin/bash или #!/ bin / sh отличаются.

для начала, #!/bin/sh-это символическая ссылка на /bin /bash в большинстве систем Linux (на Ubuntu это теперь/bin / dash)

но о том, начинать ли с /bin / sh или /bin/bash:

Bash и sh-это две разные оболочки. В основном bash-это sh, с большим количеством особенности и лучший синтаксис. Большинство команд работают одинаково, но они отличающийся.

просто предположим, что вы пишете bash скрипт, придерживайтесь /bin /bash и не / sh, потому что могут возникнуть проблемы.

$SHELL не обязательно отражает текущую оболочку. Вместо этого $SHELL является предпочтительной оболочкой пользователя, которая обычно один набор в /etc / passwd. Если вы запустите другую оболочку после ведения журнала в, вы не можете ожидать, что $SHELL будет соответствовать текущей оболочке больше.

Это мое, например, но это также может быть /root: / bin / dash или / root:/bin/sh в зависимости от того, какая оболочка у вас есть вход в passwd. Поэтому, чтобы избежать каких-либо проблем, сохраните файл passwd в /bin/bash, а затем используйте $SHELL vs.#!/ bin/bash не имеет значения, как много.

root@kali:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash

источники: http://shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash/ https://unix.stackexchange.com/questions/43499/difference-between-echo-shell-and-which-bash http://man.cx/sh http://man.cx/bash


в дополнение к тому, что говорили другие, shebang также включает подсветку синтаксиса в некоторых текстовых редакторах, например vim.