Como saio de um script em uma instrução condicional?


50

Estou escrevendo um script bash onde quero sair se o usuário não for root. O condicional funciona bem, mas o script não sai.

[[ `id -u` == 0 ]] || (echo "Must be root to run script"; exit)

Eu tentei usar em &&vez de, ;mas não funciona.

Respostas:


50

Você poderia fazer isso desta maneira:

[[ $(id -u) -eq 0 ]] || { echo >&2 "Must be root to run script"; exit 1; }

(expressão condicional "comum" com um operador binário aritmético na primeira instrução) ou:

(( $(id -u) == 0 )) || { echo >&2 "Must be root to run script"; exit 1; }

(avaliação aritmética do primeiro teste).

Observe a alteração ()-> {}- os colchetes não geram um subshell. (Procure man bashpor "subshell".)


11
Por favor, saia com um código diferente de zero, por exemplo: exit 1para entender o processo pai que ocorreu um problema.
— SamK 4/11/11

11
Você não deve usar [[para comparação numérica, use ((.
— Chris Baixo

11
@ChrisDown [[é bom, desde que você use em -eqvez de ==.
— Let_Me_Be

Corrigido o condicional, adicionada a versão aritmética, @ChrisDown.
— Mat

2
@ Mat A propósito, você pode abreviá-lo para(( EUID )) && ...
— Chris Down

21

Os parênteses em torno desses comandos criam um subshell . O eco de seu subshell "Deve ser root para executar o script" e você solicita que o subshell saia (embora já fosse, já que não havia mais comandos). A maneira mais fácil de corrigir isso é provavelmente usar apenas um if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi

Portanto, não há como fazer isso com uma única linha?
— Garrett Salão

11
sua lógica está ao contrário. no seu exemplo, se id -u == 0, o que significaria que você é root. Você quer [[ $(id -u) != 0 ]]; then.
— Tim Kennedy #

4
Se você / deve / possui uma linha, tente o tamanho: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;Observe também o $UIDque economiza a geração de um processo. Eu acho que você pode até preferir $EUID.
— janmoesen

11
@janmoesen, bom ponto. E enquanto wee ter uma variável com um valor numérico: ((UID)) && echo 'You have to be root.' && exit 1.
— manatwork

3
@janmoesen: observe que usar essa lógica inversa fará com que um script set -eseja interrompido. Uma solução para esse problema é [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true.
— 21711 Samu Hocevar

2

Com bash :

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1

Isso falharia ao sair se echofalhar (por exemplo, porque stdout não é gravável).
— Stéphane Chazelas

1

Suportes ao redor ||e &&não são necessários, pois são associativos à direita. As duas expressões a seguir são equivalentes:

expr1 || expr2 && expr3
expr1 || { expr2 && expr3 }

Então, em &&vez de ;iria funcionar muito bem, como echoretornará verdadeiro.

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1

11
Embora tudo o que você disse esteja correto, esse é um padrão ruim para aprender, porque você depende do valor de retorno de expr2. Você tem certeza de que o eco sempre retornará um status de saída 0? É muito melhor agrupar as declarações com chaves e ponto e vírgula. Essa é uma armadilha tão comum que tem sua própria entrada no BashPitfalls: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
— Flimm

11
@Limlim: eu não concordo que é um padrão ruim. Evidentemente, o uso depende de maiúsculas e minúsculas e também depende do seu conhecimento dos valores de retorno que você obterá. Nesse caso , tenho certeza de que o eco retornará 0 a 99,999% de vezes, e se pisar em um erro de gravação (o único caso não retornará 0), haverá um problema maior do que esse expr. Também há o caso em que VOCÊ está gerando os valores de retorno, então não, não é um "padrão ruim" para mim.
— ata

Acrescentarei também, como diz o wiki, que você deve usá-lo para entender a avaliação em C. De qualquer forma, um pequeno teste deve esclarecer qualquer ambiguidade.
— ata

0

isso pode ajudá-lo, no bash

[oracle@rac1 ~]$ which bash
/bin/bash
[oracle@rac1 ~]$ cat test1.sh
if [ `id -u` != 0 ]
then
echo "Must be root to run the script
 "
exit
fi

3
Isso já foi respondido e aceito. Além disso, sua resposta é quase idêntica ao que já foi publicado.
— maulinglawns

@maulinglawns, essa resposta, ao contrário dos outros, tem o mérito de ser portátil para todos os shells tipo Bourne (seria melhor se o erro fosse emitido no stderr, o status de saída fosse diferente de zero e a substituição do comando fosse citada) )
— Stéphane Chazelas
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.