Какой предпочтительный Баш Шебанг?

1132

Есть ли какой-нибудь Bashобъективный лучше Шебанга, чем другие, для большинства применений?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • так далее

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

эксцесс
источник
4
И это /usr/local/bin/bashна OpenBSD.
июня

Ответы:

1536

Вы должны использовать #!/usr/bin/env bashдля переносимости : разные * nixes помещаются bashв разные места, и использование /usr/bin/env- это обходной путь для запуска первого bashнайденного на PATH. И shнетbash .

l0b0
источник
9
Спасибо. Также похоже на то, что добавление - в конец $! / Usr / bin / env bash - ничего не даст, так как * nix в shebang допускает только один аргумент, который используется 'bash'. Это, очевидно, полезно только для предотвращения передачи вредоносных аргументов в сценарий из командной строки, если шебанг сценария является одним из других без аргументов ( /bin/shи т. Д.).
Куртоз
13
@Ray bashживет не во /binвсех системах.
ptierno
12
То же самое для меня, я просто добавил его к псевдониму: alias shebang='echo "#!/usr/bin/env bash"'теперь мне просто нужно открыть терминал и набрать shebang вместо того, чтобы идти сюда.
Oylex
19
Этот ответ обманчив. POSIX не говорит, что envна /usr/bin/env. Это может быть на /bin/envсамом деле или в любом месте, если оно находится на пути. Это может быть в /dummy/envслучае если /dummyв PATH. Сам по себе Шебанг не определен в POSIX, поэтому я мог бы #!stop toasterзапустить кофемашину USB и быть POSIX-совместимым. Так #!/usr/bin/env bashчто не лучше, чем #!/bin/bash, он может быть менее портативным в зависимости.
Darkfeline
19
@darkfeline Переносимость не абсолютна - математически невозможно создать сценарий, который будет делать то же самое на любой платформе. С 2012 по 2018 год /usr/bin/envсуществует на большем количестве машин, чем на /bin/bashxor /usr/bin/bash, поэтому сценарий, начинающийся с этой строки, будет выполнять ожидаемое действие на как можно
мая 2010 г.,
80

/bin/shобычно это ссылка на системную оболочку по умолчанию, которая часто, bashно, например, на системах Debian, имеет меньший вес dash. В любом случае, оригинальная оболочка Bourne такова sh, поэтому, если ваш сценарий использует некоторые bash(2-го поколения, «Bourne Again sh») специфические функции ( [[ ]]тесты, массивы, различные сладкие вещи и т. Д.), То вам следует быть более конкретным и использовать более позднюю версию. , Таким образом, в системах, где bash не установлен, ваш скрипт не будет работать. Я понимаю, что может быть захватывающая трилогия фильмов об этой эволюции ... но это может быть слухом.

Также обратите внимание, что когда вызывается как sh, bashв некоторой степени ведет себя как стандарт POSIX sh (см. Также документацию GNU об этом).

delicateLatticeworkFever
источник
2
Public Domain Korn Shell (pdksh) по умолчанию используется в OpenBSD.
июня
Большинство систем не будут связываться /bin/shнигде, так /usrкак это может затруднить запуск сценариев инициализации до /usrмонтирования.
МОС
@aij Я не знаю, почему я поставил «многие или большинство» там - я пользователь fedora, где /binи в /sbinтечение многих лет просто символические ссылки по умолчанию, /usr/binи /usr/sbin, так что в этом контексте /bin/shссылка на bashи фактические каталог есть /usr/bin. Но я исправлю вышеизложенное.
delicateLatticeworkFever
44

Я рекомендую использовать:

#!/bin/bash

Он не на 100% переносим (некоторые системы размещаются bashв другом месте, кроме /bin), но тот факт, что во многих существующих сценариях используются #!/bin/bashразличные операционные системы, заставляет /bin/bashпо крайней мере создать символическую ссылку на основное местоположение.

Альтернатива:

#!/usr/bin/env bash

было предложено - но нет никакой гарантии, что envкоманда находится в /usr/bin(и я использовал системы, где это не так). Кроме того, эта форма будет использовать первый экземпляр bashтекущего пользователя $PATH, который может не подходить для оболочки bash.

(Но он /usr/bin/envдолжен работать на любой достаточно современной системе, либо потому, что она envесть, /usr/binлибо потому, что система делает что-то, чтобы заставить ее работать. Система, о которой я говорил выше, была SunOS 4, которую я, вероятно, не использовал около 25 лет.)

Если вам нужен сценарий для запуска в системе, в которой его нет /bin/bash, вы можете изменить сценарий так, чтобы он указывал на правильное местоположение (что, по общему признанию, неудобно).

Я обсудил компромиссы более подробно в своем ответе на этот вопрос .

Несколько неясное обновление: одна система, которую я использую, Termux , слой , похожий на Linux для настольных компьютеров и работающий под Android, не имеет /bin/bash( bashесть /data/data/com.termux/files/usr/bin/bash), но имеет специальную поддержку для поддержки #!/bin/bash.

Кит Томпсон
источник
3
2 года спустя, и это все еще лучший совет здесь. Если простое решение не работает, то вы должны поставить под сомнение ваши предыдущие решения. Принятый и наиболее одобренный ответ не является неправильным, он просто не прав :)
Инженер-программист,
27

Использование строки shebang для вызова соответствующего интерпретатора не только для BASH. Вы можете использовать shebang для любого интерпретируемого языка в вашей системе, такого как Perl, Python, PHP (CLI) и многих других. Кстати, Шебанг

#!/bin/sh -

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

Использование envкоманды делает ваш сценарий переносимым и позволяет настраивать пользовательские среды для вашего сценария, следовательно, переносимые сценарии должны использовать

#!/usr/bin/env bash

Или для любого языка, например, для Perl

#!/usr/bin/env perl

Обязательно посмотрите на manстраницы для bash:

man bash

и env:

man env

Примечание. В системах Debian и Debian, таких как Ubuntu, shэто связано с dashnot bash. Как все системные скрипты используют sh. Это позволяет bash расти и система остается стабильной, согласно Debian.

Кроме того, чтобы сохранить вызов * nix, я никогда не использую расширения файлов в сценариях, вызываемых shebang, так как вы не можете опустить расширение при вызове исполняемых файлов, как в Windows. Команда file может идентифицировать его как скрипт.

Джейми Робиллард старший
источник
4

Это действительно зависит от того, как вы пишете свои bash-скрипты. Если ваша /bin/shссылка на bash, когда bash вызывается как sh, некоторые функции недоступны .

Если вам нужны специфичные для bash функции, не относящиеся к POSIX, используйте #!/bin/bash

Гленн Джекман
источник
3
Bash не установлен на OpenBSD. Если вы устанавливаете его через pkg_add, то он находится в /usr/local/bin, который может не быть в пути.
июня
как насчет POSIXфункции?
Николан Асад