scripts script resueltos programas programacion pasar parametros español ejercicios ejemplos comandos bash shell

bash - programas - scripts linux ejercicios resueltos



Salir del script de shell según el código de salida del proceso (9)

Tengo un script de shell que ejecuta una serie de comandos. ¿Cómo hago que el script de shell salga si alguno de los comandos sale con un código de salida distinto de cero?


" set -e " es probablemente la forma más fácil de hacer esto. Simplemente ponga eso antes de cualquier comando en su programa.


En bash esto es fácil, simplemente unirlos con &&:

command1 && command2 && command3

También puedes usar el anidado si construyes:

if command1 then if command2 then do_something else exit fi else exit fi


Si desea trabajar con $ ?, necesitará verificarlo después de cada comando, ¿desde $? se actualiza después de que cada comando sale. Esto significa que si ejecuta una tubería, solo obtendrá el código de salida del último proceso en la tubería.

Otro enfoque es hacer esto:

set -e set -o pipefail

Si coloca esto en la parte superior del script de shell, parece que bash se hará cargo de esto por usted. Como se anotó en un póster anterior, "set -e" hará que bash salga con un error en cualquier comando simple. "set -o pipefail" causará que bash se cierre con un error en cualquier comando en una tubería también.

Vea here o here para un poco más de discusión sobre este problema. Here está la sección del manual de bash en el set incorporado.


Si solo llama a exit en el bash sin parámetros, devolverá el código de salida del último comando. Combinado con OR, bash solo debe invocar exit, si el comando anterior falla. Pero no he probado esto.

command1 || exit; command2 || exit;

El Bash también almacenará el código de salida del último comando en la variable $ ?.


para el bash

# this will trap any errors or commands with non-zero exit status # by calling function catch_errors() trap catch_errors ERR; # # ... the rest of the script goes here # function catch_errors() { # do whatever on errors # # echo "script aborted, because of errors"; exit 0; }


http://cfaj.freeshell.org/shell/cus-faq-2.html#11

  1. ¿Cómo obtengo el código de salida de cmd1 en cmd1|cmd2

    En primer lugar, tenga en cuenta que el código de salida de cmd1 podría ser distinto de cero y aún no significa un error. Esto sucede, por ejemplo, en

    cmd | head -1

    puede observar un estado de salida de 141 (o 269 con ksh93) de cmd1 , pero es porque cmd fue interrumpido por una señal SIGPIPE cuando la head -1 terminó después de haber leído una línea.

    Para conocer el estado de salida de los elementos de una tubería cmd1 | cmd2 | cmd3 cmd1 | cmd2 | cmd3

    a. con zsh:

    Los códigos de salida se proporcionan en la matriz especial pipestatus. cmd1 código de salida de cmd1 está en $pipestatus[1] , el código de salida de cmd3 en $pipestatus[3] , por lo que $? siempre es lo mismo que $pipestatus[-1] .

    segundo. con bash

    Los códigos de salida se proporcionan en la PIPESTATUS especial PIPESTATUS . cmd1 código de salida de cmd1 está en ${PIPESTATUS[0]} , el código de salida de cmd3 en ${PIPESTATUS[2]} , por lo que $? siempre es lo mismo que ${PIPESTATUS: -1} .

    ...

    Para más detalles ver el siguiente http://cfaj.freeshell.org/shell/cus-faq-2.html#11 .


Después de cada comando, el código de salida se puede encontrar en el $? variable para que tengas algo como:

ls -al file.ext rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

Tienes que tener cuidado con los comandos canalizados desde el $? solo le da el código de retorno del último elemento en el conducto, en el código:

ls -al file.ext | sed ''s/^/xx: /"

no devolverá un código de error si el archivo no existe (ya que la parte sed de la tubería realmente funciona, devolviendo 0).

El shell bash realidad proporciona una matriz que puede ayudar en ese caso, que es PIPESTATUS . Esta matriz tiene un elemento para cada uno de los componentes de canalización, al que puede acceder individualmente como ${PIPESTATUS[0]} :

pax> false | true ; echo ${PIPESTATUS[0]} 1

Tenga en cuenta que esto le permite obtener el resultado del comando false , no toda la canalización. También puede hacer que la lista completa se procese como mejor le parezca:

pax> false | true | false; echo ${PIPESTATUS[*]} 1 0 1

Si quisiera obtener el código de error más grande de una tubería, podría usar algo como:

true | true | false | true | false rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done echo $rc

Esto pasa por cada uno de los elementos de PIPESTATUS a su vez, almacenándolo en rc si era mayor que el valor de rc anterior.


# #------------------------------------------------------------------------------ # run a command on failure exit with message # doPrintHelp: doRunCmdOrExit "$cmd" # call by: # set -e ; doRunCmdOrExit "$cmd" ; set +e #------------------------------------------------------------------------------ doRunCmdOrExit(){ cmd="$@" ; doLog "DEBUG running cmd or exit: /"$cmd/"" msg=$($cmd 2>&1) export exit_code=$? # if occured during the execution exit with error error_msg="Failed to run the command: /"$cmd/" with the output: /"$msg/" !!!" if [ $exit_code -ne 0 ] ; then doLog "ERROR $msg" doLog "FATAL $msg" doExit "$exit_code" "$error_msg" else #if no errors occured just log the message doLog "DEBUG : cmdoutput : /"$msg/"" doLog "INFO $msg" fi } #eof func doRunCmdOrExit


[ $? -eq 0 ] || exit $?; # exit for none-zero return code