Вы ошиблись. /bin/sh
почти никогда не является оболочкой Борна в наши дни, и именно тогда¹ у вас возникают проблемы при использовании #! /bin/sh
она -взрыва.
Оболочка Борна была написана в конце 70-х и заменила предыдущую оболочку Томпсона (, также называемую sh
). В начале 80-х Дэвид Корн написал несколько расширений для оболочки Bourne, исправил несколько ошибок и несуразностей дизайна (, а также представил некоторые )и назвал это оболочкой Korn.
В начале 90-х POSIX определилsh
язык , основанный на подмножестве оболочки Korn, и большинство¹ систем теперь изменили свой /bin/sh
либо на оболочку Korn, либо на оболочку, соответствующую этой спецификации. В случае с BSD они постепенно изменили свою /bin/sh
, первоначально (после того, как они больше не могли использовать оболочку Bourne по причинам лицензии )оболочку Almquist, клон оболочки Bourne с некоторыми расширениями ksh, поэтому она стала POSIX-совместимый.
Сегодня все системы POSIX чаще всего имеют оболочку с именем sh
(, но не обязательно в /bin
, POSIX не указывает путь к утилитам, которые он указывает ), которые в основном совместимы с POSIX. Обычно он основан на ksh88, ksh93, pdksh, bash, ash или zsh², но не на оболочке Bourne, поскольку оболочка Bourne никогда не была совместима с POSIX³. Несколько таких снарядов (bash
, zsh
,yash
и некоторые производные pdksh
включают режим совместимости с POSIX -при вызове как sh
и менее совместимы в противном случае ).
bash
(ответ GNU на оболочку Korn )на самом деле является единственной оболочкой с открытым исходным кодом (, и можно сказать, что она поддерживается только в настоящее время, поскольку другие, как правило, основаны на ksh88, который не получил никаких новых функций с 90-х годов. ), который был сертифицирован как совместимый с POSIXsh
(в рамках сертификации macOS ).
Когда вы пишете скрипт с #! /bin/sh -
ше -челкой, вы должны использовать стандартный sh
синтаксис (и также должны использовать стандартный синтаксис для утилит, используемых в этом скрипте, если вы хотите быть переносимым, при интерпретации сценария оболочки )задействована не только оболочка, тогда не имеет значения, какая реализация того стандартного sh
интерпретатора синтаксиса используется (ksh
, bash
... ).
Не имеет значения, что эти оболочки имеют расширения по сравнению со стандартом, пока вы их не используете. Это похоже на написание кода C, если вы пишете стандартный код C и не используете расширения одного компилятора (, напримерgcc
)или другого, ваш код должен компилироваться нормально, независимо от реализации компилятора, при условии, что компилятор совместим..
Здесь, с вашим #! /bin/sh
она -ударом, вашей основной проблемой будут системы, где /bin/sh
— это оболочка Борна, которая, например, не поддерживает стандартные функции, такие как $((1+1))
, $(cmd)
, ${var#pattern}
... В этом случае вам может понадобиться работа -вокруг, например:
#! /bin/sh -
if false ^ true; then
# in the Bourne shell, ^ is an alias for |, so false ^ true returns
# true in the Bourne shell and the Bourne shell only.
# Assume the system is Solaris 10 (older versions are no longer maintained)
# You would need to adapt if you need to support some other system
# where /bin/sh is the Bourne shell.
# We also need to fix $PATH as the other utilities in /bin are
# also ancient and not POSIX compatible.
PATH=`/usr/xpg6/bin/getconf PATH`${PATH:+:}$PATH || exit
export PATH
exec /usr/xpg4/bin/sh "$0" "$@"
# that should give us an environment that is mostly compliant
# to the Single UNIX Specification version 3 (POSIX.2004), the
# latest supported by Solaris 10.
fi
# rest of the script
Кстати, /bin/sh
в Ubuntu по умолчанию не является bash
. В наши дни это dash
, оболочка, основанная на NetBSD sh
, сама основанная на оболочке Almquist, которая в основном совместима с POSIX, за исключением того, что она не поддерживает многобайтовые -символы. В Ubuntu и других системах на базе Debian -вы можете выбирать между bash
и dash
для /bin/sh
с помощьюdpkg-reconfigure dash
)4 .sh
Скрипты, поставляемые с Debian, должны работать одинаково в обеих оболочках, поскольку они написаны в соответствии со стандартом политики Debian (надмножеством стандарта POSIX ). Вы, вероятно, обнаружите, что они также работают нормально в эмуляции zsh
sh
или bosh
(, вероятно, не ksh93
и yash
, которые не имеют встроенного local
(, требуемого политикой Debian. но не POSIX )).
Все системы на unix.stackexchange.com где-то имеют POSIX sh
. У большинства из них есть /bin/sh
(, вы можете найти очень редкие, у которых нет каталога /bin
, но вам, вероятно, все равно на это ), и это, как правило, интерпретатор POSIX sh
(и в редких случаях (не -стандартная )оболочка Борна вместо ).
Но sh
— это единственный исполняемый интерпретатор оболочки, который вы обязательно найдете в системе. Для других оболочек вы можете быть уверены, что macOS, Cygwin и большинство дистрибутивов GNU/Linux будут иметь bash
. Операционные системы, производные от SYSV -(Solaris, AIX... )обычно имеют ksh88, возможно, ksh93. OpenBSD, MirOS будет иметь производную от pdksh. macOS будет иметь zsh
. Но из этого не будет никакой гарантии. Нет гарантии того, что bash
или любая из этих других оболочек будет установлена в /bin
или где-либо еще (, она обычно находится в /usr/local/bin
на BSD при установке, например ). И конечно нет гарантии версии оболочки которая будет установлена.
Обратите внимание, что #! /path/to/executable
не является соглашением , это особенность всех Unix -подобных ядер (, представленная в начале 80-х Деннисом Ритчи ), которая позволяет выполнять произвольные файлы указав путь к интерпретатору в первой строке, начинающейся с #!
. Это может быть любой исполняемый файл.
Когда вы выполняете файл, первая строка которого начинается с #! /some/file some-optional-arg
, ядро завершает выполнение /some/file
с some-optional-arg
, путем к сценарию и исходными аргументами в качестве аргументов.Вы можете сделать эту первую строку #! /bin/echo test
, чтобы увидеть, что происходит:
$./myscript foo
test./myscript foo
Когда вы используете /bin/sh -
вместо /bin/echo test
, ядро выполняет /bin/sh -./myscript foo
, sh
интерпретирует код содержимого, хранящийся в myscript
, и игнорирует первую строку, поскольку это комментарий (, начинающийся с #
). ].
¹ Вероятно, единственная система, в которой сегодня кто-либо из нас столкнется с /bin/sh
, основанной на оболочке Bourne, — это Solaris 10. Solaris — одна из немногих систем Unix, которые решили сохранить оболочку Bourne для обратной совместимости (язык POSIX sh
не имеет полной обратной совместимости с оболочкой Bourne )и (, по крайней мере, для настольных и полных развертываний сервера )есть POSIX sh
в другом месте (в /usr/xpg4/bin/sh
, основанный на ksh88 ), но это изменилось в Solaris 11, где /bin/sh
теперь равно ksh93. Остальные, в основном, мертвы.
² /bin/sh
в MacOS/X раньше был zsh
, но позже был изменен на bash
. zsh
zsh
не предназначен для использования в качестве реализации POSIX sh
. Его sh
режим в первую очередь предназначен для встраивания или вызова(source
)кода POSIX sh
в zsh
скриптах
.
³ Недавно @schily расширил оболочку OpenSolaris (на основе оболочки SVR4, основанную на оболочке Bourne ), чтобы она стала совместимой с POSIX, называемой bosh
, но я не знаю что он уже используется в любой системе. Наряду с ksh88
, что делает его второй оболочкой, совместимой с POSIX -, основанной на коде оболочки Bourne
.
4 В более старых версиях вы также могли использовать mksh
или его большее воплощение POSIX lksh
. Это МирОС (бывшая оболочка MirBSD )на основе pdksh, сама основанная на оболочке Forsyth (другая повторная реализация оболочки Bourne))