Каков наиболее подходящий способ распространения сценариев оболочки, если поведение оболочек может быть изменено set
и, следовательно, непредсказуемо?
Например, rm *.txt
не будет выполняться должным образом в средах, в которых set -f
он был запущен. Как я должен убедиться, что rm *.txt
удаляет все текстовые файлы в текущем каталоге в любых средах?
Как я должен убедиться, что сценарии оболочки будут работать так, как ожидалось, прежде чем распространять их вообще?
bash
shell
shell-script
Ходж
источник
источник
shell_state=$(set +o)
... скрипт ...eval "$shell_state"
#!
чтобы указать, какие параметры оболочки вы хотите.Ответы:
Сценарии оболочки обычно обрабатываются так, как если бы они были такими же, как и любые другие исполняемые файлы, такие как двоичные файлы, сценарии Python, сценарии Perl или любые другие типы сценариев. У них есть шебанг наверху, который указывает ядру выполнять их через оболочку. Ожидается, что они будут вызываться так же, как и любая другая команда.
Таким образом, новая оболочка запускается каждый раз, когда вызывается скрипт, и любые параметры, такие как
set -f
присутствующие в вызывающей оболочке или в любом другом экземпляре оболочки в системе, не имеют значения.Конечно, пользователи могут использовать ваш сценарий вместо его запуска, например, так:
или выполнить его в оболочке, которая имеет нестандартные настройки, например:
но это не считается нормальным способом или вызовом вашего скрипта, и пользователи, которые делают это, должны ожидать, что они получат в результате.
Обратите внимание, что есть некоторые сценарии, которые предназначены для получения, а не для выполнения, потому что они предназначены для таких вещей, как изменение cwd или установка переменных среды, которые должны отражаться в среде оболочки поиска, но они в меньшинстве и это обычно делается как часть согласованного протокола. Эти файлы можно рассматривать скорее как «плагины» для любой системы, от которой они ожидают, не столько как от независимых скриптов. Например, файлы
/etc/rc*.d
с именами, которые заканчиваются на.sh
, получены из подсистемы сценариев запуска, а не выполняются, и задокументировано, что это произойдет, если вы поместите файл с таким именем в/etc/rc*.d
и когда это сделано, это сделано специально. Соглашение о присвоении имен файлам, предназначенным для получения, а не для выполнения таким образом, также применяется в других местах, но не универсально.Это правда, что файлы, предназначенные для получения таким способом, должны позаботиться о том, какие настройки могут присутствовать в среде их вызывающего, что может повлиять на поведение оболочки, но тогда согласованный протокол в идеале должен обещать предсказуемую среду выполнения.
источник
zsh
имеет функцию, которая позволяет восстановить параметры в известном наборе в локальном контексте (emulate -L zsh
), который широко используется во всех расширениях, поставляемых с zsh и написанных как код zsh. Посмотрите, как сработает система завершения bash, если вы установите такие параметры, какfailglob
.#! /bin/csh -f
вместо,#! /bin/csh
например.zshenv
. Тщательно, что вы положилиzshenv
по этой причине!emulate -L
в данном случае), комментируя один из моих ответов, и я ценю это.~/.zshenv
(где вы хотите принудительно установить настройки (обычно env vars) для всех zsh (интерактивных или нет), вызываемых под вашим именем и обычно не используемых, кроме как для обхода некоторых других проблем, не связанных с zsh), отдельно от~/.zshrc
(интерактивного настройка оболочки), так что это особенность, а не ошибка. (вы можете использовать zsh -f) Ошибка в том, что некоторые неинтерактивные оболочки bash читают ваши~/.bashrc
(например, через ssh, и вы должны добавить код для защиты от этого), или некоторые интерактивные bash (входящие в систему) не читают его (и снова, вы должны добавить код в свой,~/.bash_profile
чтобы обойти это).