Eu tenho alguns scripts bash que configurei e que usam principalmente
#!/bin/bash
mas regularmente encontro alguns que se parecem
#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex
e assim por diante.
Alguém pode explicar o significado e os benefícios dessas opções de shebang e se elas se aplicam a outras shebangs?
Responder1
Se um script /path/to/foo
começar com #!/bin/bash
, então executar /path/to/foo arg1 arg2
será equivalente a executar /bin/bash /path/too/foo arg1 arg2
. Se a linha shebang for #!/bin/bash -ex
, é equivalente a executar /bin/bash -ex /path/too/foo arg1 arg2
. Este recurso é gerenciado pelo kernel.
Observe que você pode ter apenas um argumento na linha shebang: alguns unices (como Linux) aceitam apenas um argumento, o que #!/bin/bash -e -x
levaria o bash a receber o único argumento de cinco caracteres -e -x
(um erro de sintaxe) em vez de dois argumentos -e
e -x
.
Para o shell Bourne sh
e shells derivados, como POSIX sh, bash, ksh e zsh:
-e
significa que se algum comando falhar (o que indica retornando um status diferente de zero), o script será encerrado imediatamente.-x
faz com que o shell imprima um rastreamento de execução.
Outros programas podem compreender estas opções, mas com significados diferentes.
Responder2
São opções passadas para bash
ver help set
para mais informações, neste caso:
-x Print commands and their arguments as they are executed.
-e Exit immediately if a command exits with a non-zero status.
Responder3
Gostaria apenas de mencionar uma alternativa ainda melhor – mais portátil:
#!/usr/bin/env bash
O exemplo acima usa env
para encontrar o bash
executável, que nem sempre está em /bin/bash
. Seus scripts antigos #!/bin/bash
não funcionamNixOS, por exemplo.
Se você usar env
como demonstrado acima, não poderá fornecer um argumento como -e
( bash
até onde eu sei). Mas você pode fazer isso:
#!/usr/bin/env bash
set -e
Responder4
Iniciar um script com , ou equivalentemente executar , tem o mesmo efeito que inserir dentro do script logo após sua linha.#! /path/to/bash -option
bash -option /path/to/script
set -option
#!
set -x
é essencialmente apenas para depuração; você não gostaria que fosse deixado normalmente.
O efeito set -e
é muito mais complicado do que o manual sugere. A descrição mais precisa é aproximadamente:
Depois de invocar
set -e
, se umnão testadocomando sai com um status diferente de zero, fará com que o shell saia com esse status de saída.
eu digomais precisoporque ainda é bastante vago: a lista de situações em que o comando é consideradotestadoé misterioso e difícil de prever. As regras exatas diferem entre shells e até mudam entre versões do mesmo shell.
set -e
faznãofaz com que o Bash saia em resposta ao status de saída diferente de zero de qualquer comando:
- entre
if
e ;elif
then
ou - entre
while
e ;until
do
ou - seguindo
!
; ou - seguido por
||
ou&&
ou&
(embora para&
o correspondentewait
oufg
possa falhar); ou - seguido por
|
, a menos queset -o pipefail
esteja em vigor; ou - dentro
$( ... )
quando usado como parte de um comando (não atribuições e/ou redirecionamentos simples, o que significa quefoo=$( bar )
falhará sebar
falhar, maslocal foo=$( bar )
não falhará); ou - dentro de um comando composto onde o acima se aplica; ou
- dentro de uma função shell invocada de qualquer lugar que se aplique acima.
Os efeitos em comandos compostos e funções shell são recursivos.
Como o próprio shell sai com um status diferente de zero, o efeito pode se propagar para fora de um subshell.
A !
isenção aplica-se mesmo que o estado de saída invertido seja ignorado.
Por outro lado, set -e
os gatilhos emtodos os outrosstatus diferente de zero, independentemente de significar "falha" ou simplesmente "falso". Por exemplo, ((x++))
terá um status de saída de "falha" diferente de zero quando x
for inicialmente 0.
Por ser uma bagunça, existe uma escola de pensamento que diz que set -e
deve ser evitado em favor da verificação explícita de todos os comandos.
Ou se você ainda quiser usar set -e
, lembre-se de escrever !
na frente de qualquer ((arithmetic))
grupo.