¿Cómo salgo de un script en una declaración condicional?

50

Estoy escribiendo un script bash donde quiero salir si el usuario no es root. El condicional funciona bien, pero el script no sale.

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

He intentado usar en &&lugar de ;pero tampoco trabajo.

Garrett Hall
fuente

Respuestas:

50

Podrías hacerlo de esta manera:

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

(expresión condicional "ordinaria" con un operador binario aritmético en la primera instrucción), o:

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

(evaluación aritmética para la primera prueba).

Observe el cambio ()-> {}- los corchetes no generan una subshell. (Busque man bash"subshell").

Estera
fuente
1
Salga con un código que no sea cero, por ejemplo: exit 1para hacer entender el proceso padre que ocurrió un problema.
SamK
1
No debe usar [[para la comparación numérica, use ((.
Chris Down el
1
@ChrisDown [[está bien, siempre que lo uses en -eqlugar de ==.
Let_Me_Be
Se corrigió el condicional, se agregó la versión aritmética, @ChrisDown.
Mat
2
@Mat Por cierto, puede acortarlo a(( EUID )) && ...
Chris abajo
21

Los paréntesis alrededor de esos comandos crean una subshell . Su eco de subshell "Debe ser root para ejecutar el script" y luego le dice al subshell que salga (aunque ya lo habría hecho, ya que no había más comandos). La forma más fácil de solucionarlo es probablemente usar un if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi
Michael Mrozek
fuente
Entonces, ¿no hay forma de hacer esto con una frase?
Garrett Hall el
1
Tu lógica es al revés. en su ejemplo, si id -u == 0, lo que significaría que usted es root. Que desea [[ $(id -u) != 0 ]]; then.
Tim Kennedy el
44
Si usted / debe / tiene una línea, intente esto para el tamaño: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;también tenga en cuenta el $UID, lo que ahorra el proceso de desove. Creo que incluso podrías preferirlo $EUID.
Janmoesen
1
@janmoesen, buen punto. Y mientras wee tener una variable con un valor numérico: ((UID)) && echo 'You have to be root.' && exit 1.
manatwork el
3
@janmoesen: tenga en cuenta que el uso de dicha lógica inversa provocará un script que set -eabortará. Una solución a ese problema es [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true.
sam hocevar el
2

Con bash :

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1
Ciro
fuente
Eso no podría salir si echofalla (por ejemplo, porque stdout no se puede escribir).
Stéphane Chazelas
1

Corchetes ||y &&no son necesarias ya que estos son asociativo por la derecha. Las siguientes dos expresiones son equivalentes:

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

Entonces, en &&lugar de ;funcionaría bien, como echovolverá cierto.

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1
ata
fuente
1
Si bien todo lo que dijo es correcto, este es un mal patrón para aprender, ya que depende del valor de retorno de expr2. ¿Está seguro de que echo siempre devolverá un estado de salida 0? Es una idea mucho mejor agrupar las declaraciones con llaves y punto y coma. Esta es una trampa tan común que tiene su propia entrada en BashPitfalls: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm
1
@Flimm: No estoy de acuerdo con que sea un mal patrón. Evidentemente, su uso depende de las mayúsculas y minúsculas, y también depende de su conocimiento de los valores de retorno que obtendrá. En este caso , estoy seguro de que echo devolverá 0 el 99.999% de las veces, y si pisa un error de escritura (el único caso no devolverá 0) hay un problema mayor que este expr. También existe el caso en el que USTED está generando los valores de retorno, así que no, no es un "mal patrón" per se para mí.
ata
También agregaré, como dice en la wiki, que debes usarlo para entender la evaluación de C. De todos modos, una pequeña prueba debería aclarar cualquier ambigüedad.
ata
0

esto podría ayudarte, en 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
fuente
3
Esto ya ha sido respondido y aceptado. Además, su respuesta es casi idéntica a la que ya se ha publicado.
Maulinglawns
@maulinglawns, esa respuesta, al contrario de las otras, tiene el mérito de ser portátil a todos los shells tipo Bourne (sería mejor si el error se emitiera en stderr, el estado de salida no era cero y la sustitución del comando se citaba aunque )
Stéphane Chazelas