Правильный способ распространения сценариев оболочки

8

Каков наиболее подходящий способ распространения сценариев оболочки, если поведение оболочек может быть изменено setи, следовательно, непредсказуемо?

Например, rm *.txtне будет выполняться должным образом в средах, в которых set -fон был запущен. Как я должен убедиться, что rm *.txtудаляет все текстовые файлы в текущем каталоге в любых средах?

Как я должен убедиться, что сценарии оболочки будут работать так, как ожидалось, прежде чем распространять их вообще?

Ходж
источник
shell_state=$(set +o) ... скрипт ...eval "$shell_state"
mikeserv
Вы можете запустить эти команды в верхней части самого скрипта или изменить, #!чтобы указать, какие параметры оболочки вы хотите.
HalosGhost

Ответы:

6

Сценарии оболочки обычно обрабатываются так, как если бы они были такими же, как и любые другие исполняемые файлы, такие как двоичные файлы, сценарии Python, сценарии Perl или любые другие типы сценариев. У них есть шебанг наверху, который указывает ядру выполнять их через оболочку. Ожидается, что они будут вызываться так же, как и любая другая команда.

Таким образом, новая оболочка запускается каждый раз, когда вызывается скрипт, и любые параметры, такие как set -fприсутствующие в вызывающей оболочке или в любом другом экземпляре оболочки в системе, не имеют значения.

Конечно, пользователи могут использовать ваш сценарий вместо его запуска, например, так:

. /path/to/your/script

или выполнить его в оболочке, которая имеет нестандартные настройки, например:

sh -f /path/to/your/script

но это не считается нормальным способом или вызовом вашего скрипта, и пользователи, которые делают это, должны ожидать, что они получат в результате.

Обратите внимание, что есть некоторые сценарии, которые предназначены для получения, а не для выполнения, потому что они предназначены для таких вещей, как изменение cwd или установка переменных среды, которые должны отражаться в среде оболочки поиска, но они в меньшинстве и это обычно делается как часть согласованного протокола. Эти файлы можно рассматривать скорее как «плагины» для любой системы, от которой они ожидают, не столько как от независимых скриптов. Например, файлы /etc/rc*.dс именами, которые заканчиваются на .sh, получены из подсистемы сценариев запуска, а не выполняются, и задокументировано, что это произойдет, если вы поместите файл с таким именем в/etc/rc*.dи когда это сделано, это сделано специально. Соглашение о присвоении имен файлам, предназначенным для получения, а не для выполнения таким образом, также применяется в других местах, но не универсально.

Это правда, что файлы, предназначенные для получения таким способом, должны позаботиться о том, какие настройки могут присутствовать в среде их вызывающего, что может повлиять на поведение оболочки, но тогда согласованный протокол в идеале должен обещать предсказуемую среду выполнения.

Celada
источник
1
zshимеет функцию, которая позволяет восстановить параметры в известном наборе в локальном контексте ( emulate -L zsh), который широко используется во всех расширениях, поставляемых с zsh и написанных как код zsh. Посмотрите, как сработает система завершения bash, если вы установите такие параметры, как failglob.
Стефан Шазелас
Некоторые оболочки читают ваш файл настроек даже при вызове для интерпретации скриптов. Вот почему вы обычно используете #! /bin/csh -fвместо, #! /bin/cshнапример.
Стефан Шазелас
@ StéphaneChazelas Хаха, да, действительно. Конечно, это часть того, почему использование csh - плохая идея , верно? :-) Но я думаю, у Zsh это тоже есть в форме zshenv. Тщательно, что вы положили zshenvпо этой причине!
Селада
@ StéphaneChazelas, кстати, я не первый раз учу меня чему-то, чего я не знал ( emulate -Lв данном случае), комментируя один из моих ответов, и я ценю это.
Селада
Ну, ~/.zshenv(где вы хотите принудительно установить настройки (обычно env vars) для всех zsh (интерактивных или нет), вызываемых под вашим именем и обычно не используемых, кроме как для обхода некоторых других проблем, не связанных с zsh), отдельно от ~/.zshrc(интерактивного настройка оболочки), так что это особенность, а не ошибка. (вы можете использовать zsh -f) Ошибка в том, что некоторые неинтерактивные оболочки bash читают ваши ~/.bashrc(например, через ssh, и вы должны добавить код для защиты от этого), или некоторые интерактивные bash (входящие в систему) не читают его (и снова, вы должны добавить код в свой, ~/.bash_profileчтобы обойти это).
Стефан Шазелас