Bash Shebang для чайников?

Bash Shebang для чайников?

У меня есть несколько настроенных bash-скриптов, которые в основном используют

#!/bin/bash

но я регулярно сталкиваюсь с некоторыми, которые выглядят как

#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex

и так далее.

Может ли кто-нибудь объяснить значение и преимущества этих опций шебанга и применимы ли они к другим шебангам?

решение1

Если скрипт /path/to/fooначинается с #!/bin/bash, то выполнение /path/to/foo arg1 arg2эквивалентно выполнению /bin/bash /path/too/foo arg1 arg2. Если строка shebang — #!/bin/bash -ex, то это эквивалентно выполнению /bin/bash -ex /path/too/foo arg1 arg2. Эта функция управляется ядром.

Обратите внимание, что в строке shebang можно переносить только один аргумент: некоторые UNIX-системы (например, Linux) принимают только один аргумент, поэтому это #!/bin/bash -e -xприведет к тому, что bash получит единственный пятисимвольный аргумент -e -x(синтаксическая ошибка) вместо двух аргументов -eи -x.

Для оболочки Bourne shи производных оболочек, таких как POSIX sh, bash, ksh и zsh:

  • -eозначает, что если какая-либо команда завершится неудачно (на что указывает возврат ненулевого статуса), скрипт будет немедленно завершен.
  • -xзаставляет оболочку выводить трассировку выполнения.

Другие программы могут понимать эти параметры, но с другим значением.

решение2

Это параметры, передаваемые для bashпросмотра help setдополнительной информации, в данном случае:

-x  Print commands and their arguments as they are executed.
-e  Exit immediately if a command exits with a non-zero status.

решение3

Я бы хотел упомянуть еще более лучшую (в смысле более портативную) альтернативу:

#!/usr/bin/env bash

В примере выше используется envдля поиска bashисполняемого файла, который не всегда находится в /bin/bash. Старые #!/bin/bashскрипты не работают наNixOS, например.

Если вы используете env, как показано выше, вы не можете предоставить аргумент, такой как -eto bash(насколько я знаю). Но вы можете сделать это вместо этого:

#!/usr/bin/env bash
set -e

решение4

Запуск скрипта с помощью или эквивалентный запуск имеет тот же эффект, что и вставка внутрь скрипта сразу после его строки.#! /path/to/bash -optionbash -option /path/to/scriptset -option#!

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

Эффект set -eнамного сложнее, чем предполагает руководство. Более точное описание примерно такое:

После вызова set -e, еслинепроверенныйкоманда завершается с ненулевым статусом, это приведет к завершению работы оболочки с этим статусом завершения.

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

set -eделаетнетзаставляют Bash завершать работу в ответ на ненулевой статус завершения любой команды:

  • между if/ elifи then; или
  • между while/ untilи do; или
  • следующий !; или
  • за которым следует ||или &&или &(хотя &соответствующее waitили fgможет не сработать); или
  • за которым следует |, если не set -o pipefailдействует; или
  • внутри $( ... ), когда используется как часть команды (не просто назначения и/или перенаправления, что означает, что foo=$( bar )в случае сбоя произойдет сбой bar, но local foo=$( bar )не произойдет); или
  • в составе составной команды, где применяется вышеизложенное; или
  • внутри функции оболочки, вызываемой из любого места, где применимо вышеизложенное.

Эффекты составных команд и функций оболочки являются рекурсивными.

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

Исключение !применяется даже в случае игнорирования инвертированного статуса выхода.

И наоборот, set -eтриггеры накаждый второйненулевой статус, независимо от того, означает ли он "fail" или просто "false". Например, ((x++))будет иметь ненулевой статус выхода "fail", когда xизначально равен 0.

Поскольку это действительно запутанная ситуация, существует мнение, что этого set -eследует избегать в пользу явной проверки всех команд.

Или, если вы все же хотите использовать set -e, не забудьте написать !перед всеми ((arithmetic))группами.

Связанный контент