Вы получили это назад. /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-совместимой3. Некоторые из этих оболочек ( bash
, zsh
, yash
и некоторые pdksh
производные включить режим POSIX-совместимый при вызове , как sh
и в меньшей степени соответствует иным образом ).
bash
(GNU-ответ на оболочку Korn) на самом деле является единственной оболочкой с открытым исходным кодом (и можно сказать, что поддерживается только в настоящее время, поскольку остальные, как правило, основаны на ksh88, который не получил никакой новой функции с 90-х годов), который был сертифицирован как быть POSIX-совместимым sh
(как часть сертификации MacOS).
Когда вы пишете сценарий с #! /bin/sh -
самоуверенностью, вы должны использовать стандартный sh
синтаксис (а также использовать стандартный синтаксис для утилит, используемых в этом сценарии, если вы хотите быть переносимым, при интерпретации оболочки используется не только оболочка). script), тогда не имеет значения, какая реализация этого стандартного sh
синтаксического интерпретатора используется ( ksh
, bash
...).
Неважно, что эти оболочки имеют расширения над стандартом, если вы их не используете. Это похоже на написание кода на C, если вы пишете стандартный код на C и не используете расширения одного компилятора (например gcc
) или другого, ваш код должен компилироваться нормально, независимо от реализации компилятора, при условии, что компилятор совместим.
Здесь, с #! /bin/sh
она Взрыва, ваша главная задача будет системы , где /bin/sh
является Bourne оболочки , которая, например , не поддерживает стандартные функции , такие как $((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
Кстати, Ubuntu /bin/sh
не bash
по умолчанию. В dash
наши дни это оболочка на основе NetBSD sh
, сама основанная на оболочке Almquist, которая в основном совместима с POSIX, за исключением того, что она не поддерживает многобайтовые символы. В Ubuntu и других систем Debian на базе, вы можете выбрать между bash
и dash
для /bin/sh
с dpkg-reconfigure dash
) 4 . sh
Сценарии, поставляемые с Debian, должны работать одинаково в обеих оболочках, так как они написаны в стандарте политики Debian (расширенный набор стандарта POSIX). Вы , вероятно, обнаружите , что они также работают КИ в zsh
«S sh
эмуляции или bosh
(вероятно , не , ksh93
ни , yash
которые не имеет local
встроенной команды (требуется политика Debian , но не POSIX)).
Все системы в unix.stackexchange.com имеют sh
где-то POSIX . Большинство из них имеют /bin/sh
(вы можете найти очень редкие, у которых нет /bin
каталога, но вы, вероятно, не заботитесь об этом), и это, как правило, sh
интерпретатор POSIX (а в редких случаях (нестандартная) оболочка Bourne вместо этого). ).
Но 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 для обратной совместимости ( sh
язык POSIX не полностью обладает обратной совместимостью с оболочкой Bourne) и (по крайней мере, для настольных систем и полных серверов) имеет POSIX в sh
другом месте (на /usr/xpg4/bin/sh
основе ksh88), но это изменилось в Solaris 11, где /bin/sh
теперь находится ksh93. Другие в основном несуществующие.
² из MacOS / X , используемый , чтобы быть , но позже изменено на . Это не основной фокус для использования в качестве реализации POSIX . Его режим в первую очередь для возможности вставлять или вызывать ( ) код POSIX в скриптах/bin/sh
zsh
bash
zsh
sh
sh
source
sh
zsh
³ Недавно @schily расширила оболочку OpenSolaris (основанную на оболочке SVR4, основанную на оболочке Bourne), чтобы она стала совместимой с POSIX, bosh
но я не знаю, используется ли она в любой системе. Наряду с ksh88
этим делает его второй POSIX-совместимой оболочкой на основе кода оболочки Bourne.
4 В более старых версиях вы также можете использовать mksh
или более lksh
инкарнацию POSIX . Это оболочка MirOS (ранее MirBSD), основанная на pdksh, сама основанная на оболочке Forsyth (еще одно повторное воплощение оболочки Bourne))