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.

Garrett Hall
fonte

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".)

Esteira
fonte
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
Michael Mrozek
fonte
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
Cyrus
fonte
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
ata
fonte
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
sandeep kazipeta
fonte
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