Я думаю, то, что Сэм хочет сделать, может быть невозможным.
В какой степени возможен полуобработанный обходной путь, зависит от ...
- ... оболочки пользователей по умолчанию и
- ...какие альтернативные оболочки им разрешено использовать.
Если я правильно понимаю требование Сэма, он хочет иметь «сценарий», myscript
, то есть ...
- ... не непосредственно исполняемый через вызов его по имени
myscript
(то есть с chmod a-x
); - ... не косвенно исполняемыйдля пользователей, вызывая
sh myscript
или bash myscript
- ... только , запуская содержащиеся в нем функции и команды, если вызывается путем его получения:
. myscript
Первое, что нужно учитывать, это
- Для вызова сценария напрямую по его имени (
myscript
) требуется первая строка в сценарии, такая как #!/bin/bash
или аналогичная.Это напрямую определит, какой установленный экземпляр исполняемого файла bash (или символическая ссылка) будет вызван для запуска содержимого скрипта.Это будет новый процесс оболочки.Для этого требуется, чтобы в самом файле сценария был установлен флаг исполняемого файла. - Запуск сценария путем вызова двоичного файла оболочки с именем сценария (путь +) в качестве аргумента (
sh myscript
), аналогично «1».- за исключением того, что не требуется устанавливать исполняемый флаг, и указанная первая строка с хеш-бэнгом тоже не требуется .Единственное, что нужно, это то, что вызывающему пользователю нужен read доступ к файлу скрипта. - Вызов скрипта путем получения имени файла (
. myscript
) очень похож на «1».- за исключением того, что это не новая оболочка, которая вызывается.Все команды скрипта выполняются в текущей оболочке , используя его окружение (а также «загрязняя» свое окружение любыми (новыми) переменными, которые он может устанавливать или изменять. (Обычно это очень опасная вещь для выполнения: но здесь его можно использовать для выполнения exit $RETURNVALUE
при определенных условиях ....)
Для '1.':
Легко достичь: chmod a-x myscript
предотвратит непосредственное выполнение myscript
, но не выполнит требования «2» и «3.».
для «2» и «3.»:
Гораздо сложнее достичь. Для вызовов sh myscript
требуется чтение привилегий для файла. Так что очевидным выходом может показаться chmod a-r
myscript
. Однако, это также запретит '3'.: вы также не сможете получить исходный текст сценария.
Так как насчет написания сценария способом, который использует Bashism ? Bashism - это особый способ сделать что-то, что другие оболочкине понимаю: использование определенных переменных, команд и т. д. Это может быть использовано внутрискрипт для обнаружения этого условия и «что-то сделать» с ним (например, «display warning.txt», «mailto admin» и т. д.).Но ни в коем случае нельзя, чтобы это помешало sh
или bash
или любой другой оболочке прочитать и попытаться выполнить все следующие команды / строки, записанные в сценарии, если вы не уничтожите оболочку, вызвав exit
.
Примеры: в Bash, среда, видимая сценарием, знает о $BASH
, $BASH_ARGV
, $BASH_COMMAND
, $BASH_SUBSHELL
, BASH_EXECUTION_STRING
....Если вызывается sh
(также если sourced внутри sh
), исполняющая оболочка увидит все эти $BASH_*
как пустые переменные окружения.Опять же, это можно использовать внутри скрипта, чтобы обнаружить это условие и «сделать что-то» ... , но не помешать запуску следующих команд!
Я сейчас это предполагаю...
- ... сценарий использует
#!/bin/bash
в качестве первой строки, - ... пользователи установили Bash в качестве оболочки и вызывают команды в следующей таблицеот Bash и это их оболочка для входа ,
- ...
sh
доступна и является символической ссылкой на bash
или dash
.
Это будет означать, что возможны следующие вызовы с перечисленными значениями для переменных среды
vars+invok's | ./scriptname | sh scriptname | bash scriptname | . scriptname
---------------+--------------+---------------+-----------------+-------------
$0 | ./scriptname | ./scriptname | ./scriptname | -bash
$SHLVL | 2 | 1 | 2 | 1
$SHELLOPTS | braceexpand: | (empty) | braceexpand:.. | braceexpand:
$BASH | /bin/bash | (empty) | /bin/bash | /bin/bash
$BASH_ARGV | (empty) | (empty) | (empty) | scriptname
$BASH_SUBSHELL | 0 | (empty) | 0 | 0
$SHELL | /bin/bash | /bin/bash | /bin/bash | /bin/bash
$OPTARG | (empty) | (empty) | (emtpy) | (emtpy)
Теперь вы можете добавить логику в ваш текстовый скрипт:
- Если
$0
не равно -bash
, тогда выполните exit $SOMERETURNVALUE
.
Если сценарий был вызван через sh myscript
или bash myscript
, он будет
выйти из вызывающей оболочки. Если он был запущен в текущей оболочке, он будет
продолжать бежать. (Предупреждение: в случае, если скрипт имеет какие-либо другие операторы exit
,
ваша текущая оболочка будет «убита» ...)
Так что вставьте в свой неисполняемый файл myscript.txt
в начале его что-то вроде
это может сделать что-то близкое к вашей цели:
echo BASH=$BASH
test x${BASH} = x/bin/bash && echo "$? : FINE.... You're using 'bash ...'"
test x${BASH} = x/bin/bash || echo "$? : RATS !!! -- You're not using BASH and I will kick you out!"
test x${BASH} = x/bin/bash || exit 42
test x"${0}" = x"-bash" && echo "$? : FINE.... You've sourced me, and I'm your login shell."
test x"${0}" = x"-bash" || echo "$? : RATS !!! -- You've not sourced me (or I'm not your bash login shell) and I will kick you out!"
test x"${0}" = x"-bash" || exit 33