Есть ли какая-то причина, чтобы шебанг указывал на / bin / sh, а не на / bin / bash?


53

В большинстве сценариев оболочки, которые я видел (кроме тех, которые я сам не написал), я заметил, что shebang установлен в #!/bin/sh. Это не очень удивляет меня в старых скриптах, но есть и в довольно новых скриптах.

Есть ли основания для предпочтения /bin/shболее /bin/bash, так как bashэто в значительной степени повсеместно, и часто по умолчанию, на многих машинах Linux и BSD восходящих более десяти лет?


23
Это хорошая часть для использования, /bin/shесли вы не используете определенные bashфункции. Однажды вам может понадобиться использовать один из ваших сценариев в системе, в которой он не установлен (удаленный сервер, встроенный компьютер ...)
Матье

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

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

3
@JulesMazur ...the answers so far are fairly subjective...«субъективное» утверждение по существу основано на мнении. /bin/bashдолжен использоваться только когда явно необходим bash. За 40 с лишним лет, как разработчик, задолго до bashэтого я почти никогда не нуждался в этом явно, кроме как при тестировании. (Я также стараюсь избегать расширений оболочки, но большинство моих сценариев предназначены для распространения.) Многие сценарии в сети также должны быть предназначены для широкого использования.
user2338816

2
@ user2338816 мой плохой, я имел ввиду цель . Спасибо за ваши очки!
Жюль

Ответы:


84
  1. Существуют системы, не поставляющие bash по умолчанию (например, FreeBSD).
  2. Даже если bash установлен, он может не находиться в /bin.
  3. Большинство простых скриптов не требуют bash.
  4. Использование оболочки POSIX более переносимо, и сценарии будут работать в самых разных системах.

17
Другая причина: часто / bin / sh быстрее, чем bash, или, по крайней мере, загружается быстрее (из-за меньшего размера).
Дероберт

5
@derobert, /bin/shбыстрее, если это не так bash, есть еще несколько систем, таких как OS / X или RHEL, где /bin/shесть bash.
Стефан Шазелас

1
Нет. Некоторые ОС связывают это, потому что bash обратно совместим.
Sobrique

7
Многие сценарии предполагают, что /bin/shэто так /bin/bash. Переключение Ubuntu с bash на dash сломало их всех.
Атаманроман

19
@atamanroman: Во-первых, скрипты были неверны, их следовало использовать, #!/bin/bashесли они хотели Bash (в этом нет ничего плохого!). Изменения в основном были сделаны в Debian. Это улучшило взаимодействие с пользователем, оказало ощутимое влияние на время запуска системы. Это также положительно повлияло на безопасность, см. «Shellshock».
Дитрих Эпп

28

Большинство системных скриптов в (связанных с Debian: Ubuntu, Mint и т. Д.) Linux написаны так, чтобы работать в более быстром тире, которое по умолчанию / bin / sh в этих системах. Причина двоякая:

  • Скорость системы. Меньший код тире загружается быстрее, а также работает быстрее. С некоторыми (маленькими?) Дополнительными усилиями (затратами) для программистов сценариев оболочки.

  • Безопасность. Наличие разнообразия оболочек помогает устойчивости к ошибкам. Системы Debian в большинстве случаев не были уязвимы для шеллшока, потому что оболочка по умолчанию не имела такой уязвимости.

Bash действительно является оболочкой по умолчанию для пользователей , так как она более мощная и имеет гораздо больше элементов, облегчающих программирование. Это также значение по умолчанию shв Mac OS (которое связано с / bin / sh). Тем не менее, вызов bashс именем ссылки shзаставляет его начинаться как posix-совместимая оболочка.


2
Более ограниченный набор доступных инструментов более простой оболочки затрудняет написание кода для нее (пожалуйста, избегайте фанатичной войны с этим). Вот почему некоторым пользователям нравится zsh, в котором доступно даже больше инструментов, чем bash. Мне больше нравится Bash, так как это баланс между обеими крайностями.

4
@RobertL, многие средства, добавленные в ksh и принятые bash, существуют, потому что они существенно упрощают процесс написания надежных и правильных сценариев. Например, без различных дополнений, позволяющих безопасно выполнять косвенное назначение и оценку, можно использовать себя evalс сопутствующей защитой; Точно так же, без встроенной поддержки регулярных выражений, можно использовать внешние команды (при значительном снижении производительности) для сопоставления даже в пределах одной строки и т. д.
Чарльз Даффи

1
@RuiFRibeiro, в Debian нет ничего статически связанного. Dash более ограничен, но ограничен в основном интерактивными функциями (без завершения и т. Д.), Поэтому он быстрее для сценариев.
Ян Худек

21

Другие отмечают, что предпосылки вопроса о том, что оболочка Bourne Again является стандартной и вездесущей, совершенно неверны.

В дополнение к этому, есть действительно веские причины для использования чего-то другого, кроме оболочки Bourne Again, для интерпретации сценариев оболочки. Эти причины мотивировали в Ubuntu и большой проект Debian, в течение ряда лет, чтобы удалить bashisms и сделать так как многие из сценариев оболочки управляют инициализации системы (который был много сценариев оболочки с системой 5 rc) и установки пакетов / использование удаления в Оболочка Debian Almquist вместо оболочки Bourne Again.

Проще говоря: оболочка Bourne Again, битком набитая интерактивными функциями, не является самым быстрым интерпретатором оболочки для POSIX-совместимого сценария оболочки. Поэтому, если кто-то может сделать свои сценарии оболочки POSIX-совместимыми, интерпретируя их с помощью более легкой программы, такой как оболочка Debian Almquist, ваша система будет работать лучше. (В конце концов, Debian пришлось внести небольшие коррективы в оболочку Almquist, чтобы добавить поддержку нескольких не-POSIX-конструкций оболочки, которые просто слишком глубоко и широко внедрены и слишком полезны, чтобы от них избавиться.)

Результатом всего этого стало значительное увеличение производительности начальной загрузки.

Итак, здесь нужно рассмотреть два различных класса оболочки:

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

Обратите внимание, что говорить об этом как о «предпочтении /bin/sh» слишком упрощенно. На самом деле у Debian было как минимум две цели:

  1. Перед лицом администраторов, использующих оболочку Debian Almquist, оболочку Z (в режиме POSIX), оболочку Bourne Again (в режиме POSIX), оболочку MirBSD Korn и другие, поскольку /bin/sh

    1. ... сделать сценарии максимально переносимыми, чтобы переключение между /bin/shотображаемыми объектами не нарушало их; или же

    2. … Создание непереносимых сценариев явно нацелено на правильную программу-интерпретатор , а не просто ожидает эту /bin/shкарту к ней.

  2. Было сделано, что оболочка Debian Almquist является отображением по умолчанию /bin/shвместо оболочки Bourne, так что те сценарии, которые были POSIX-совместимыми (или, точнее, совместимыми с политикой Debian), выполнялись быстрее.

И, конечно, как только кто-то входит в это, он может пойти намного дальше; такие как рассмотрение компромиссных эффективности подобных /bin/trueи /usr/bin/clearбыть сценарии оболочки или скомпилированных программ. Но это выходит за рамки этого ответа, к счастью. ☺

Все это, конечно, не является чем-то новым и даже специфичным для Unix. Еще на рубеже веков я написал и опубликовал интерпретатор командной строки, который выпускался как в «интерактивном», так и в «неинтерактивном» виде, объясняя именно это разделение в документе и отмечая разницу между переменными COMSPECи OS2_SHELLсредой. Точно так же обсуждение удаления ошибок в System V Debian rcи сценариях установки / удаления пакетов восходит к 1990-м годам.

дальнейшее чтение


2
«В конце концов, Debian пришлось внести небольшие коррективы в оболочку Almquist, чтобы добавить поддержку пары конструкций не-POSIX, которые просто слишком глубоко и широко внедрены и слишком полезны, чтобы от них избавиться». - Какая из ваших многочисленных ссылок содержит информацию об этом? Это звучит очень интересно. :)
Wildcard

3
ИМХО, производительность - только мотиватор, чтобы заставить людей согласиться с изменениями. Первоначальной большой причиной изменений было то, что bash продолжал нарушать обратную совместимость. Лично мне приходилось исправлять проблемы с bash по крайней мере 3 раза в моей карьере, потому что скрипт работал в одной версии bash, но не работал в другой (обычно это происходит после обновления ОС). Дэш не просто немного более быстрый переводчик. Это также намного более стабильно с точки зрения поведения.
Slebetman

Мне было бы интересно, подходят ли комментарии на Schily Bourne Shellстранице руководства , см. Schilytools.sourceforge.net/bosh.html , чтобы люди могли понять, как написать переносимый скрипт (это зависит только Bourne Shell featuresот 1989 года). Что я сделал, так это упомянул все улучшения, которых не было в старых Bourne Shells. Кстати, мне также интересно узнать список bashisms в тире.
Schily

8

Есть ли какая-то причина, чтобы шебанг указывал на / bin / sh, а не на / bin / bash?

Да. Превосходный ответ @ Марко обрисовывает в общих чертах это хорошо.

Что я должен использовать в моем шебанге?

При написании своих собственных сценариев, вы должны указывать шебангу на самое общее, что вы проверяли.

В моей системе (Centos 6.6) shесть ссылка на bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Это означает, что я всегда использую #!/bin/bashв своем шебанге, если не убедился, что в моем сценарии нет башим.

Установив шебанг, #!/bin/shвы обещаете, что скрипт будет работать со всеми реализациями sh.

Это гораздо большее обещание, чем говорить, что скрипт будет работать с bash.

Вот пример скрипта, который будет вести себя некорректно в зависимости от того, какую shреализацию использует система:

#!/bin/sh
n=1
a=$((++n))
echo $n

При использовании bashскрипта будет напечатано:

2

При использовании dashскрипта будет напечатано:

1

Если я хочу использовать #!/bin/shто, что мне нужно сделать?

  • Проверьте скрипт с checkbashisms- Обратите внимание, что это не найдет все bashims. Это не нашло башизма в моем сценарии выше
  • Протестируйте скрипт, используя другую shреализацию. Обычно dashя провожу тестирование , однако ожидаю, что некоторые удары или дашимы все еще могут ускользнуть.

На странице DashAsBinSh в вики Ubuntu есть много интересной информации.


6
«При написании ваших собственных сценариев вы должны указывать на shebang самые общие вещи, с которыми вы тестировали .... Установив shebang на #! / Bin / sh, вы обещаете, что скрипт будет работать со всеми реализациями sh «. Отличный момент. +1, и ты заставил меня переосмыслить, как я буду писать свои шебанги на будущее. Спасибо! :)
Wildcard

2
Ну, не все реализации /bin/sh; только POSIX-совместимые.
Blacklight Shining

4

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

/bin/shэто единственный интерпретатор сценариев, который доступен на всех, кто называет себя Unix. Но на огромном количестве устаревших систем /bin/shи связанных утилит даже не совместимы со спецификацией POSIX.1-1996 «оболочка и утилиты», не говоря уже о чем-то более современном. Стандартно совместимые инструменты - это необязательное дополнение, установленное в /usr/xpg4каком-либо таком неочевидном месте. 1 Сценарии на языке оболочки с переносимым подмножеством еще более утомительны и подвержены ошибкам, чем сценарии на языке оболочки POSIX. (Прочитайте configureсценарий, сгенерированный Autoconf, если вы мне не верите. Достаточно просто установки, чтобы убедить вас.)

Но если вы можете предположить, что установлен любой другой интерпретатор сценариев (например, Bash), то вы можете предположить, что установлен интерпретатор для лучшего языка сценариев . Например, Perl более доступен, чем Bash.

Поэтому вы никогда не должны писать #! /bin/bashскрипт, потому что, если это вариант, лучше вариант с языком.

1 Например, Solaris 10 и старше поставили оригинальную оболочку Bourne как /bin/sh. Мне сообщили, что Solaris 11 обновил его до ksh93.


3
На каком языке вы будете писать скрипт для загрузки системы? Или внутри роутера SOHO (ограниченные встроенные системы)? Или в Android? Оболочка будет доступна во всех этих случаях. Perl нет.

1
Есть некоторые неточности в связанных с Solaris частях вашего ответа. В Solaris 10 и более ранних версиях /bin/sh- это не POSIX.1-1996, а фактически синтаксис, предшествующий POSIX, с оригинальной оболочкой Bourne. Это делает #!/bin/shочень плохой сценарий для запуска сценариев с этими выпусками. Переносимые скрипты в Solaris будут использоваться, #!/usr/xpg4/bin/shчто не будет очень переносимо в других ОС. В последней версии Solaris Oracle Solaris 11, впервые выпущенный в 2011 году, /bin/shпредставляет собой современную ksh93версию, которая соответствует последним спецификациям POSIX и имеет множество современных расширений.
Jlliagre

1
@BinaryZebra: «Оболочка» будет доступна, да. Но bash не обязательно является такой оболочкой (в частности, большинство SOHO-маршрутизаторов используют ashее с busybox), и я склонен считать, что zwol прав, что perl более доступен, чем bash.
Бен Фойгт

1
@BenVoigt Я комментирую это предложение «Единственная оставшаяся причина написать сценарий оболочки». Есть еще некоторые экземпляры, которым нужна оболочка для некоторых задач (не для всех). Это были некоторые примеры из головы. OTOH В системах с достаточным объемом памяти (почти все в современных стандартах) и достаточной мощностью установка Perl (или Python, или ....) довольно быстрая и простая. Однако я не сторонник какой-либо конкретной оболочки. Где вы читаете это в моем комментарии?

2
Совершенно не согласен с вашим весьма неубедительным и неэффективным утверждением, что «если bashдоступно, значит, это лучший язык, поэтому вы никогда не должны писать никакого bashкода». Кроме того, как указывает @sixtyfootersdude, вы всегда должны использовать, #!/bin/bashесли только вы не проверили, что ваш скрипт работает с любой оболочкой POSIX.
Подстановочный

0

Вы должны на самом деле использовать либо

#! /bin/env sh

или же

#! /bin/env bash

таким образом вы вызываете любую оболочку по тому, как они установлены в этой системе.

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


6
Из этого ответа : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Это, вероятно, также относится к shи bash.
Жюль

12
Нет, вы не должны использовать #!/bin/envчто-либо в переносимом скрипте. Вполне разумно предположить, что /bin/shсуществует и является работающей, POSIX-совместимой оболочкой. С другой стороны, ни одна из моих систем не имеет /bin/env.
Blacklight Shining

Также хороший момент.
Жюль

1
@ Blacklight Shining, это определенно неправильно предполагать POSIX-совместимую оболочку /bin/sh. POSIX не требует этого, а скорее определяет другие правила для получения POSIX-совместимой среды на платформе, сертифицированной POSIX.
Schily

4
/usr/bin/envне является общедоступным ...
vonbrand
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.