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


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и когда это сделано, это сделано специально. Соглашение о присвоении имен файлам, предназначенным для получения, а не для выполнения таким образом, также применяется в других местах, но не универсально.

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


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чтобы обойти это).
— Стефан Шазелас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.