Estoy estudiando el contenido de este archivo de preinst que el script ejecuta antes de que el paquete se desempaquete de su archivo de Debian (.deb).
El script tiene el siguiente código:
#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
if [ -d /usr/share/MyApplicationName ]; then
echo "MyApplicationName is just installed"
return 1
fi
rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section
Mi primera consulta es sobre la línea:
set -e
Creo que el resto del script es bastante simple: comprueba si el administrador de paquetes Debian / Ubuntu está ejecutando una operación de instalación. Si es así, comprueba si mi aplicación acaba de instalarse en el sistema. Si es así, el script imprime el mensaje "MyApplicationName se acaba de instalar" y finaliza ( return 1
significa que termina con un "error", ¿no?).
Si el usuario solicita al sistema de paquetes Debian / Ubuntu que instale mi paquete, el script también elimina dos directorios.
¿Es correcto o me estoy perdiendo algo?
man set
set +e
Respuestas:
De
help set
:Pero algunos lo consideran una mala práctica (preguntas frecuentes sobre bash y autores de preguntas frecuentes sobre irc freenode #bash). Se recomienda usar:
para ejecutar la
do_something
función cuando se producen errores.Ver http://mywiki.wooledge.org/BashFAQ/105
fuente
trap 'exit' ERR
ERR
trampa no es heredada por las funciones de shell, por lo que si tiene funciones,set -o errtrace
oset -E
le permitirá establecer la trampa una vez y aplicarla globalmente.trap 'exit' ERR
hacer nada diferente deset -e
?set -e
detiene la ejecución de un script si un comando o canalización tiene un error, que es lo opuesto al comportamiento predeterminado del shell, que es ignorar los errores en los scripts. Escribahelp set
un terminal para ver la documentación de este comando incorporado.fuente
set -o pipefail
que se puede usar para propagar errores, de modo que el valor de retorno del comando de canalización no sea cero si uno de los comandos anteriores salió con un estado distinto de cero.-o pipefail
solo significa que el estado de salida del primer-o errexit
comando distinto de cero (es decir, error en términos) de la tubería se propaga hasta el final. Los comandos restantes en la tubería aún se ejecutan , incluso conset -o errexit
. Por ejemplo:echo success | cat - <(echo piping); echo continues
, dondeecho success
representa un éxito, pero comando falibles, se imprimirásuccess
,piping
ycontinues
, sin embargofalse | cat - <(echo piping); echo continues
, lafalse
que representa el comando ahora erroring en silencio, todavía se imprimapiping
antes de salir.Según bash: el manual Set Builtin , si
-e
/errexit
está configurado, el shell sale inmediatamente si una tubería que consiste en un solo comando simple , una lista o un comando compuesto devuelve un estado distinto de cero.Por defecto, el estado de salida de una tubería es el estado de salida del último comando en la tubería, a menos que la
pipefail
opción esté habilitada (está deshabilitada de manera predeterminada).Si es así, el estado de retorno de la tubería del último comando (el más a la derecha) para salir con un estado distinto de cero, o cero si todos los comandos salen con éxito.
Si desea ejecutar algo al salir, intente definir
trap
, por ejemplo:¿Dónde
onexit
está su función para hacer algo al salir, como a continuación, que está imprimiendo el rastro simple de la pila :Hay una opción similar
-E
/errtrace
que atraparía en ERR en su lugar, por ejemplo:Ejemplos
Ejemplo de estado cero:
Ejemplo de estado distinto de cero:
Ejemplos de estado de negación:
Prueba con
pipefail
ser deshabilitado:Prueba con
pipefail
estar habilitado:fuente
Encontré esta publicación mientras intentaba averiguar cuál era el estado de salida de un script que fue abortado debido a un
set -e
. La respuesta no me pareció obvia; De ahí esta respuesta. Básicamente,set -e
aborta la ejecución de un comando (por ejemplo, un script de shell) y devuelve el código de estado de salida del comando que falló (es decir, el script interno, no el script externo) .Por ejemplo, supongamos que tengo el script de shell
outer-test.sh
:El código para
inner-test.sh
es:Cuando ejecuto
outer-script.sh
desde la línea de comandos, mi script externo termina con el código de salida del script interno:fuente
Creo que la intención es que el guión en cuestión falle rápidamente.
Para probar esto usted mismo, simplemente escriba
set -e
en un indicador de bash. Ahora, intenta correrls
. Obtendrá un listado de directorio. Ahora, escribelsd
. Ese comando no se reconoce y devolverá un código de error, por lo que su solicitud de bash se cerrará (debido aset -e
).Ahora, para comprender esto en el contexto de un 'script', use este script simple:
Si lo ejecuta como está, obtendrá el listado del directorio
ls
en la última línea. Si descomentaset -e
y vuelve a ejecutar, no verá la lista del directorio ya que bash detiene el procesamiento una vez que encuentra el error delsd
.fuente
Esta es una vieja pregunta, pero ninguna de las respuestas aquí discute el uso de
set -e
akaset -o errexit
en los scripts de manejo de paquetes de Debian. El uso de esta opción es obligatorio. en estos scripts, según la política de Debian; la intención aparentemente es evitar cualquier posibilidad de una condición de error no controlada.Lo que esto significa en la práctica es que debe comprender en qué condiciones los comandos que ejecuta podrían devolver un error y manejar cada uno de esos errores explícitamente.
Los errores comunes son, por ejemplo,
diff
(devuelve un error cuando hay una diferencia) ygrep
(devuelve un error cuando no hay coincidencia). Puede evitar los errores con el manejo explícito:(Observe también cómo nos encargamos de incluir el nombre del script actual en el mensaje y de escribir mensajes de diagnóstico en un error estándar en lugar de en la salida estándar).
Si no es realmente necesario o útil un manejo explícito, explícitamente no haga nada:
(El uso de la cáscara
:
comando no-op es un poco oscuro, pero se ve con bastante frecuencia).Solo para reiterar,
es taquigrafía para
es decir, explícitamente decimos que
other
debe ejecutarse si y solo sisomething
falla. La escritura manualif
(y otras declaraciones de control de flujo de shell comowhile
,until
) también es una forma válida de manejar un error (de hecho, si no fuera así, los scripts de shell conset -e
nunca podrían contener declaraciones de control de flujo!)Y también, solo para ser explícito, en ausencia de un controlador como este,
set -e
causaría que todo el script falle inmediatamente con un error sidiff
encuentra una diferencia o sigrep
no encuentra una coincidencia.Por otro lado, algunos comandos no producen un estado de salida de error cuando desea que lo hagan. Los comandos comúnmente problemáticos son
find
(el estado de salida no refleja si realmente se encontraron archivos) ysed
(el estado de salida no revelará si el script recibió alguna entrada o si realizó algún comando con éxito). Una protección simple en algunos escenarios es canalizar a un comando que grita si no hay salida:Cabe señalar que el estado de salida de una tubería es el estado de salida del último comando en esa tubería. Entonces, los comandos anteriores enmascaran completamente el estado de
find
ysed
, y solo le dicen sigrep
finalmente tuvo éxito.(Bash, por supuesto, sí
set -o pipefail
; pero los scripts de paquetes de Debian no pueden usar las funciones de Bash. La política dicta firmemente el uso de POSIXsh
para estos scripts, aunque esto no siempre fue así).En muchas situaciones, esto es algo a tener en cuenta por separado cuando se codifica a la defensiva. A veces tiene que, por ejemplo, pasar por un archivo temporal para poder ver si el comando que produjo esa salida finalizó con éxito, incluso cuando la expresión idiomática y la conveniencia de otro modo le indicarían que usara una tubería de shell.
fuente
fuente