Подтвердить что ты не робот

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

Я использую Bash

$ echo $SHELL
/bin/bash

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

Обновление. В определенных ситуациях файл обрабатывается только как script с помощью Шебанг, пример

$ 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
4b9b3361

Ответ 1

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

Из FreeBSD выполните страницу руководства:

 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 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() выполняет программу, на которую указывает имя файла. имя файла должно быть либо двоичный исполняемый файл, либо script, начиная с строки форма:

#! interpreter [optional-arg]

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

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


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

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

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

Из 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. Я видел bash в /usr/bin, /usr/local/bin, /opt/fsf/bin и /opt/gnu/bin, чтобы назвать несколько.

Поэтому обычно рекомендуется использовать env;

#!/usr/bin/env bash

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

#!/bin/sh

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

Ответ 2

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

Ответ 3

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

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

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

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

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

find /tmp -name "*.foo" -exec sh -c 'myscript "[email protected]"' sh {} + 

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

Ответ 4

Вас может заинтересовать раннее описание от Dennis M Ritchie (dmr), который изобрел #!:

От uucp Thu Jan 10 01:37:58 1980

. > От dmr Thu Jan 10 04:25:49 1980 удаленный от исследования

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

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

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

3) Сценарии оболочки могут быть установлены пользователем-идентификатором.

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

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

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

   #! /bin/sh

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

Надеюсь, что это поможет

Ответ 5

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

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

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

Ответ 6

$SHELL и #!/bin/ bash или #!/bin/sh разные.

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

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

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

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

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

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

[email protected]:~/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

Ответ 7

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