Используйте #! / 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.


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.


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

@MichaelDurrant В этом случае вам не нужно и не следует писать сценарий оболочки. Вместо этого вам следует использовать любой из множества лучших языков сценариев, которые являются опцией, когда вам не нужна полная переносимость.
Звол
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.