Когда это #!/bin/bash
более уместно, чем #!/bin/sh
в сценарии оболочки?
linux
shell-script
Hendré
источник
источник
bash
функции и синтаксис, а неsh
функции и синтаксис.vim
выделитbash
-измы, если у вашего сценария есть#!/bin/sh
шебанг. Я только изменяю это,bash
если вещи становятся достаточно волосатыми, чтобы начать нуждаться в bash-функциях.$(...)
особенно неприятно. Кроме того, некоторые из них неуловимы [<(...)
иcmd >& file
не выделяют никаких ошибок, например, у них просто нет специального выделения для того, что они имеют в виду, с или безg:is_bash
]Ответы:
Короче говоря:
Существует несколько оболочек, которые реализуют расширенный набор спецификации POSIX sh . В разных системах
/bin/sh
может быть ссылка на ash, bash, dash, ksh, zsh и т. Д. (Это всегда будет совместимо с sh - никогда не csh или fish.)Пока вы придерживаетесь
sh
только функций, вы можете (и, вероятно, даже должны) их использовать,#!/bin/sh
и скрипт должен работать нормально, независимо от того, какая это оболочка.Если вы начнете использовать специфичные для bash функции (например, массивы), вам следует специально запросить bash - потому что, даже если
/bin/sh
bash уже запущен в вашей системе, он может не работать в любой другой системе, и ваш скрипт не будет работать там. (Конечно, то же самое относится и к zsh и ksh.) Вы можете использовать shellcheck для определения bashisms.Даже если скрипт предназначен только для личного использования, вы можете заметить, что некоторые операционные системы меняются
/bin/sh
во время обновлений - например, в Debian он был bash, но позже был заменен на очень минимальный тире. Скрипты, которые использовали bashisms, но#!/bin/sh
внезапно сломались.Тем не мение:
Даже
#!/bin/bash
не очень правильно. В разных системах bash может жить в/usr/bin
или/usr/pkg/bin
или/usr/local/bin
.Более надежный вариант
#!/usr/bin/env bash
, который использует $ PATH. (Хотя самenv
инструмент также не гарантирован, он/usr/bin/env
все же работает на большем количестве систем, чем/bin/bash
делает.)источник
/bin/sh
он попытается имитироватьsh
функции (см. Справочную страницу ), но не уверен, что в этом режиме доступны определенные функции bash.env
Это инструмент posix, его нужно найти в большинстве дистрибутивов, но я не уверен, что некоторые могут не уважать posix./bin
: « Приложения должны учитывать, что стандартным PATH для оболочки нельзя считать либо / bin / sh, либо / usr / bin / sh, и его следует определить путем запроса PATH, возвращаемого getconf PATH, для обеспечения того, чтобы возвращаемый путь был абсолютным, а не встроенным в оболочку ". Также см. Этот вопрос и, в частности, этот ответ .#!
работы скриптов?echo foo ^ cat
выдаетfoo ^ cat
в POSIX sh, и выдает толькоfoo
в Bourne (так как там^
есть символ канала).Используйте shebang, соответствующий оболочке, которую вы фактически использовали для разработки и отладки вашего скрипта. Т.е. если ваша оболочка входа в систему
bash
и вы запускаете свой скрипт как исполняемый в вашем терминале, используйте#!/bin/bash
. Не просто предполагайте, что, поскольку вы не использовали массивы (или любую другуюbash
функцию, о которой вам известно), вы можете выбрать любую оболочку, которая вам нравится. Существует много тонких различий между оболочками (echo
функциями, циклами, как вы их называете), которые невозможно обнаружить без надлежащего тестирования.Учтите это: если вы уйдете,
#!/bin/bash
а у ваших пользователей его нет, они увидят четкое сообщение об ошибке, что-то вродеБольшинство пользователей могут исправить это за одну минуту, установив соответствующий пакет. С другой стороны, если вы замените shebang на
#!/bin/sh
и протестируете его в системе, где/bin/sh
есть символическая ссылка/bin/bash
, у ваших пользователей, которые не имеют,bash
будут проблемы. Скорее всего, они увидят загадочные сообщения об ошибках, такие как:Это может занять несколько часов, и не будет никакого понятия о том, какую оболочку они должны были использовать.
Существует не так много причин, почему вы захотите использовать другую оболочку в shebang. Одна из причин заключается в том, что используемая вами оболочка не получила широкого распространения. Другой способ - повысить производительность,
sh
которая в некоторых системах значительно выше, и ваш сценарий станет узким местом в производительности. В этом случае тщательно протестируйте свой сценарий с помощью целевой оболочки, а затем измените шебанг.источник
Вы должны только когда-либо использовать
#! /bin/sh
.Вы никогда не должны использовать расширения bash (или zsh, или fish, или ...) в сценарии оболочки.
Вы должны когда-либо писать сценарии оболочки, которые работают с любой реализацией языка оболочки (включая все «служебные» программы, которые идут вместе с самой оболочкой). В эти дни вы, вероятно, можете считать POSIX.1-2001 ( не -2008) авторитетным для того, на что способны оболочка и утилиты, но помните, что однажды вас могут попросить перенести ваш скрипт в унаследованную систему (например, Solaris). или AIX), чьи оболочки и утилиты были заморожены около 1992 года.
Что, серьезно ?!
Да серьезно.
Вот в чем дело: Shell - ужасный язык программирования. Единственное, что у него есть
/bin/sh
- это единственный интерпретатор сценариев, который гарантированно будет в каждой установке Unix.Вот еще одна вещь: некоторая итерация основного интерпретатора Perl 5 (
/usr/bin/perl
) с большей вероятностью будет доступна в случайно выбранной установке Unix, чем(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
есть. Другие хорошие языки сценариев (Python, Ruby, node.js и т. Д. - я даже включу PHP и Tcl в эту категорию при сравнении с оболочкой) также примерно так же доступны, как bash и другие расширенные оболочки.Поэтому, если у вас есть возможность написания bash-скрипта, у вас есть возможность использовать не просто ужасный язык программирования.
Теперь, простые сценарии оболочки, такие, которые запускают несколько программ последовательно из задания cron или чего-то еще, нет ничего плохого в том, чтобы оставить их как сценарии оболочки. Но простые сценарии оболочки не нуждаются в массивах, функциях или
[[
даже. И вы должны писать сложные сценарии оболочки только тогда, когда у вас нет другого выбора. Например, сценарии Autoconf по-прежнему являются сценариями оболочки. Но эти сценарии должны выполняться при каждом воплощении,/bin/sh
которое имеет отношение к настраиваемой программе. и это означает, что они не могут использовать какие-либо расширения. Возможно, вам не нужно заботиться о старых проприетарных Unix-файлах в наши дни, но вам, вероятно, следует заботиться о текущих BSD с открытым исходным кодом, некоторые из которых не устанавливаютсяbash
по умолчанию, и встроенные среды, которые дают вам только минимальную оболочку иbusybox
.В заключение, в тот момент, когда вы обнаруживаете, что вам нужна функция, недоступная в переносимом языке оболочки, это признак того, что сценарий стал слишком сложным, чтобы оставаться сценарием оболочки. Перепишите его на лучшем языке.
источник
sh
. Это, однако, далеко от заявления о том, что вы никогда не должны использовать другие оболочки. Каждый день пишутся тысячи (а может быть, и больше) сценариев, и подавляющее большинство из них будет работать только на одной машине. Ваш совет имеет смысл для производственного кода, но не для ежедневных «sysdaminy» заданий, для которых написано большинство сценариев. Если я знаю, что мой скрипт будет когда-либо использоваться только мной и на машине с Linux, bash подойдет.Как правило, если время важнее, чем функциональность, вы будете использовать более быструю оболочку. sh часто имеет псевдоним dash и, как правило, используется для задач cron root или пакетных операций, где каждая (нано) секунда считается.
источник
Чтобы быть еще более кратким, используйте,
sh
если переносимость между большинством систем наиболее важна, иbash
если вы хотите использовать некоторые из его специфических функций, таких как массивы, если версия bash поддерживает это.источник
Самый безопасный путь. когда он жестко запрограммирован, будет / usr / bin /,
shellOfChoice
но сейчас я всегда пытаюсь использовать новое соглашение, поскольку «местоположение по умолчанию» при изменении PATH может измениться так:#! / usr / bin / env sh или
#! / usr / bin / env bash
или, например, для сценариев perl
#! / usr / bin / env perl -w
Конечно, когда у вас есть причина, по которой скрипт НИКОГДА не будет автоматически принимать новый PATH, продолжайте жестко его кодировать, и тогда / usr / bin / что-то должно быть наиболее вероятным путем для использования.
источник