Как правило, сценарии оболочки содержат следующий комментарий в первой строке файла сценария: #!/bin/sh
. Согласно проведенным мною исследованиям это называется «хэш-бэнг», и это обычный комментарий. Этот комментарий сообщает Unix, что этот файл выполняется Bourne Shell в каталоге /bin
.
Мой вопрос начинается с этого момента. До сих пор я не видел этот комментарий, как #!/bin/bash
. Это всегда #!/bin/sh
. Однако в дистрибутивах Ubuntu нет программы Bourne Shell. У них есть Bourne Again Shell (Баш).
С этой точки зрения, правильно ли размещать комментарий #!/bin/sh
в сценариях оболочки, написанных в дистрибутивах Ubuntu?
shebang
Ответы:
#!/bin/sh
должен работать на всех Unix и Unix-подобных дистрибутивах. Обычно он считается самым переносимым хэш-бангом, если ваш сценарий поддерживает POSIX. Предполагается, что/bin/sh
оболочка представляет собой оболочку, которая реализует стандарт оболочки POSIX, независимо от того, что представляет собой оболочка, маскирующаяся под/bin/sh
оболочку.#!/bin/sh
обычно это просто ссылка, так как оболочка Bourne больше не поддерживается. Во многих системах Unix/bin/sh
это будет ссылка/bin/ksh
или/bin/ash
, во многих системах Linux на основе RHEL это будет ссылка/bin/bash
, однако в Ubuntu и многих системах на основе Debian это ссылка/bin/dash
. Все оболочки, при вызове какsh
, перейдут в режим совместимости POSIX.Хотя hashbang является важным заполнителем, поскольку он обеспечивает гораздо большую переносимость, чем другие методы, при условии, что ваш сценарий строго соответствует POSIX (повторяется, чтобы подчеркнуть важность).
Примечание. Когда
bash
вызывается в режиме POSIX, он по-прежнему допускает некоторые вещи[[
, не относящиеся к POSIX, такие как массивы и многое другое. Эти вещи могут потерпеть неудачу в несистемнойbash
.источник
/bin/ash
.#! /
вместо просто#!
.Вы получили это назад.
/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}
... В этом случае вам может понадобиться обходные как:Кстати, Ubuntu
/bin/sh
неbash
по умолчанию. Вdash
наши дни это оболочка на основе NetBSDsh
, сама основанная на оболочке Almquist, которая в основном совместима с POSIX, за исключением того, что она не поддерживает многобайтовые символы. В Ubuntu и других систем Debian на базе, вы можете выбрать междуbash
иdash
для/bin/sh
сdpkg-reconfigure dash
) 4 .sh
Сценарии, поставляемые с Debian, должны работать одинаково в обеих оболочках, так как они написаны в стандарте политики Debian (расширенный набор стандарта POSIX). Вы , вероятно, обнаружите , что они также работают КИ вzsh
«Ssh
эмуляции или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
чтобы увидеть, что происходит:Когда вы используете
/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))источник
exec sh "$0" "$@"
после установкиPATH
? Это следует подобратьsh
из правильного места, подумал бы я.$PATH
.$(...)
режимы emacs / vi, расширения тильды / скобки (те, которые изначально были из csh), fc, typeset, псевдоним , синтаксис функции в стиле ksh ...Да, вы можете использовать
#!/bin/sh
в скрипте, потому что/bin/sh
(мы надеемся) предусмотрены в таких системах, обычно по какой-то ссылке, котораяbash
ведет себя (более или менее), как еслиsh
бы. Вот система Centos7, например, которая ссылаетсяsh
наbash
:Вы также можете использовать,
#!/bin/bash
если вы пишетеbash
сценарий только для этой системы и хотите использоватьbash
функции. Однако такие сценарии будут страдать от проблем с переносимостью, например, в OpenBSD, гдеbash
он устанавливается, только если администратор берет на себя труд, чтобы установить его (а я нет), а затем он устанавливается/usr/local/bin/bash
, а не/bin/bash
.#!/bin/sh
Сценарий строго POSIX должен быть более переносимым.источник
sh
Bash вызывается как , Bash переходит в режим POSIX после чтения файлов запуска». - gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode#!/bin/bash
точно, чтобы использовать преимущества не-POSIX-функций./bin/sh
это символическая ссылкаbash
, это правильно? Я точно знаю, что это CentOS.bash
. Двоичный файл знает, какое имя использовалось для его вызова, и когда он называется,sh
он действует как старая школа Борнаsh
.Ты спрашивал
Ответ зависит от того, что вы пишете в сценарии оболочки.
Если вы строго используете переносимые POSIX-совместимые сценарии и не используете команды, специфичные для bash, тогда вы можете их использовать
/bin/sh
.Если вы знаете, что когда-либо используете скрипт только на машине с bash, и вы хотите использовать специфичный для bash синтаксис, то вам следует использовать
/bin/bash
Если вы хотите быть уверены, что сценарий будет работать на разных машинах Unix, вам следует использовать только POSIX-совместимый синтаксис, и
/bin/sh
Если вы регулярно используете другую оболочку (например , КШ , ЗШ или Tcsh ), и вы хотите использовать этот синтаксис в скрипте, то вы должны использовать соответствующий интерпретатор (например
/bin/ksh93
,/bin/zsh
или/bin/tcsh
)источник
"#!" комментарий не всегда использует
/bin/bash
или/bin/sh
. Он просто перечисляет, каким должен быть интерпретатор, а не только для сценариев оболочки. Например, мои скрипты на Python обычно начинаются с#!/usr/bin/env python
.Теперь разница между
#!/bin/sh
и в#!/bin/bash
том, что/bin/sh
не всегда является символической ссылкой на/bin/bash
. Часто, но не всегда. Ubuntu является заметным исключением здесь. Я видел сценарии, работающие нормально в CentOS, но не работающие в Ubuntu, потому что автор использовал специфичный для bash синтаксис с#!/bin/sh
.источник
Извините за то, что налил немного холодной воды на все эти замечательные ответы, в которых говорится, что
/bin/sh
он присутствует во всех системах Unix - он присутствует, за исключением наиболее используемой системы Unix всех времен: Android.В Android есть встроенная оболочка
/system/bin/sh
, и, как правило, нет возможности создать/bin/sh
ссылку, даже в корневой системе (из-за того, что система заблокирована с помощью selinux и ограниченных наборов возможностей (7)).Для тех, кто скажет, что android не является POSIX-совместимым: ни большинство дистрибутивов Linux и BSD. И существование
/bin/sh
с этим путем не является обязательным стандартом :источник
getconf
? Например, в Solaris 11.4, это будет в/usr/bin
? Один в/usr/xpg4/bin
(для соответствия SUSv2), другой в/usr/xpg6/bin
(для соответствия SUSv3)?/usr/xpg7/bin
(для SUSv4)?/bin/sh