Используйте #! / Bin / sh или #! / Bin / bash для совместимости с Ubuntu-OSX и простоты использования и POSIX

18

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

Было #!/bin/shбы рекомендовано, если совместимость со всеми системами Unix является абсолютным требованием?

В моем случае единственные операционные системы, о которых я забочусь, это Ubuntu (Debian) и OSX. Учитывая это, могу ли я использовать #!/bin/bashи быть уверенным, что он будет работать на обеих системах?
Не облегчит ли это также использование сценариев с более современным и понятным синтаксисом для команд? Использование #!/bin/shтакже связано с использованием POSIX?

Майкл Даррант
источник
1
Наверное, стоит отметить, что многие дистрибутивы начали объединяться /binи /usr/bin. В результате, в #!/usr/bin/env <shname>наши дни , вероятно, лучше использовать для мобильности.
HalosGhost

Ответы:

15

Для начала, если вы можете сделать предположение, что Bash предустановлен (что, насколько мне известно, имеет место во всех перечисленных вами системах), используйте следующий hashbang для совместимости:

#!/usr/bin/env bash

это вызывает все, что bashпроисходит, независимо от того, находится он в /binили /usr/local/bin.

Хотя на большинстве систем в широком диапазоне (включая AIX, Solaris, несколько разновидностей BSD) bash, envоказывались в разных местах, всегда оказывались /usr/bin/env. Уловка, однако, не моя, но от автора Поваренной книги Bash.

В любом случае, да, Bash позволит вам использовать некоторые «современные» функции, которые сделают вашу жизнь проще.

Например двойные скобки:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

в то время как в традиционных диалектах оболочки вам придется прибегнуть к:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

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

Вы также можете использовать довольно удобные выражения, такие как $((2**10))или другие арифметические выражения, встроенные в $((expression))синтаксис.

Использование backticks для подоболочек хорошо, хотя и немного устарело. Но вложенные возможности $(command ...)вызовов гораздо удобнее, так как вам не придется избегать многих вещей на разных уровнях подоболочек.

Это всего лишь несколько вещей, которые Bash дает вам по сравнению с традиционным shсинтаксисом POSIX .

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

0xC0000022L
источник
Bash - это очень полезный инструмент, но будьте осторожны, чтобы не использовать его для запуска служб, которые могут быть уязвимы к ошибке скриптов Bash, например, access.redhat.com/security/cve/CVE-2014-6271 . Придерживайтесь shдля таких задач.
Рик-777
1
Рик-777, эта уязвимость была сильно преувеличена, и, на мой взгляд, ваш комментарий - FUD. Если системная служба работает под Bash, она никоим образом не уязвима для этой ошибки. Эта ошибка уязвима только в том случае, если она блокирует процесс bash, в то же время позволяя удаленным пользователям прямой доступ к одной или нескольким переменным среды, как в FastCGI, и даже тогда только к непатентованным версиям bash. В системах, shсвязанных с bash, уязвимость не будет устранена с помощью sh.
Score_ под
11

В Debian и Ubuntu /bin/shесть dashоболочка, совместимая с POSIX. Если вы укажете #!/bin/sh, вы должны ограничить себя инструкциями POSIX в вашем скрипте. (Преимущество в том, что он dashзапускается быстрее bash, поэтому ваш скрипт может выполнить свою работу за меньшее время.)

Во многих (большинстве?) Других системах Linux, /bin/shименно bashпоэтому многие сценарии пишутся в #!/bin/shвиде строки shebang, даже если они используют bashрасширения.

Если вы хотите использовать bashрасширения, самый безопасный подход во всех системах - указать #!/bin/bash; таким образом, вы явно указываете свою зависимость от bash. Вы должны сделать это в Debian и Ubuntu. В качестве дополнительного бонуса, при запуске /bin/sh bashдеактивирует некоторые расширения (подробнее см. Описание режима bashPOSIX ); так что уточнение #!/bin/bashнеобходимо, чтобы получить полную выгоду bash.

На OS X /bin/bashтоже /bin/shесть и есть bash. Указание #!/bin/bashбудет работать там хорошо.

Стивен Китт
источник
5

Да, и OSX и Linux придут с /bin/bash. Вы должны быть в полной безопасности. Однако это не POSIX. Оболочка POSIX используется в /bin/shбольшинстве (всех?) Систем, и это наиболее переносимый подход и единственный способ быть совместимым с POSIX.

Обратите внимание, что в то время как во многих системах он /bin/shуказывает на bash, в других он может указывать на разные оболочки. Это символическая ссылка dashна Debian и Ubuntu, например. Кроме того, даже если /bin/shссылка является ссылкой bash, поведение оболочки изменяется, когда она вызывается как sh(из man bash, выделено мной):

Если bash вызывается с именем sh, он пытается максимально близко имитировать поведение при запуске исторических версий sh, при этом также соответствует стандарту POSIX. При вызове в качестве интерактивной оболочки входа в систему или неинтерактивной оболочки с параметром --login он сначала пытается читать и выполнять команды из / etc / profile и ~ / .profile в указанном порядке. Опция --noprofile может использоваться для подавления этого поведения. Когда вызывается как интерактивная оболочка с именем sh, bash ищет переменную ENV, расширяет ее значение, если оно
определяется и использует расширенное значение в качестве имени файла для чтения и выполнения. Поскольку оболочка, вызываемая как sh, не пытается читать и выполнять команды из любых других файлов запуска, опция --rcfile не действует. Неинтерактивная оболочка, вызываемая с именем sh, не пытается читать другие файлы запуска. Когда вызывается как sh, bash переходит в режим posix после чтения файлов запуска.

Тердон
источник
2

Если совместимость со «всеми системами Unix» является абсолютным требованием, а если нет, то почему вы пишете сценарий оболочки? - тогда, да, вы должны использовать #! /bin/sh, потому что Bash не гарантированно будет установлен где-либо , не говоря уже о /bin.

Это на самом деле намного, намного хуже, чем это. Если вам нужна совместимость со всеми системами Unix, это включает в себя такие вещи, как Solaris и AIX, которые заморозили их оболочки примерно в 1995 году. Это означает, что вы должны использовать такие вещи, как старомодный sort +Nсинтаксис - что более новые системы упали! И это также означает, что нет функций оболочки, нет массивов, нет [[ ... ]], нет ${foo#glob}, нет $(( ... ))для арифметики, возможно, нет $( ... )подстановки команд в стиле, маленькие и недокументированные верхние пределы того, как большой ввод может быть получен, ...

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

zwol
источник
Благодарю. Как первоначально было сказано: «В моем случае единственные ОС, которые меня волнуют, это Ubuntu (Debian) и OSX». Это единственные две системы, которые я использовал (и я часто их использую) за последние 5 лет, поэтому я пишу сценарий оболочки, который будет работать только на них. Мне вообще не нужен универсальный сценарий и ограничения, которые он представляет.
Майкл Даррант
@MichaelDurrant В этом случае вам не нужно и не следует писать сценарий оболочки. Вместо этого вам следует использовать любой из множества лучших языков сценариев, которые являются опцией, когда вам не нужна полная переносимость.
Звол