¿Cómo puedo atrapar errores e interrupciones en GNU hacer?
Pregunta
Me pregunto si hay una manera de poner en práctica trap
en make
GNU, similar a la incorporada en BASH
?
Si el usuario pulsa CTRL-C
, o si make
misma falla (no nula salida), me gustaría llamar a un objetivo o macro en particular.
Solución
No. el manejo de señales de GNU make ya deja mucho que desear. Desde el interior de su manejador de señales, que llama a funciones como printf
que no son seguros para ser llamado desde un controlador de señales. He visto a este causa problemas, por ejemplo, reglas .DELETE_ON_ERROR
no siempre se ejecutan si stderr
se redirige a stdout
.
Por ejemplo, en una caja de CentOS 7.4:
-
Cree el siguiente
Makefile
:.DELETE_ON_ERROR: foo: touch $@ sleep 10
-
Abre en
vim
y correr:make
, - Si bien está durmiendo, golpeó Ctrl - C
Vim / hacer impresiones
Press ENTER or type command to continue
touch foo
sleep 10
^C
shell returned 130
Interrupt: Press ENTER or type command to continue
Hacer se envió una señal de interrupción, pero todavía existe foo
.
Otros consejos
En este punto en el tiempo, GNU make no tiene soporte nativo.
Hay una solución fiable sin embargo:
.PHONY: internal-target external-target
external-target:
bash -c "trap 'trap - SIGINT SIGTERM ERR; <DO CLEANUP HERE>; exit 1' SIGINT SIGTERM ERR; $(MAKE) internal-target"
internal-target:
echo "doing stuff here"
Esto llama interrupciones, terminaciones y cualquier código de salida distinto de cero.
Tenga en cuenta el $(MAKE)
por lo que anula la línea de órdenes y hacer que las opciones se pasan a submake.
En la trampa:
- manejador trampa clara (con -)
- hacer la limpieza
- salida con el código de salida distinto de cero, por lo que la construcción de herramientas de automatización informan la acumulación fallado.
DELETE_ON_ERROR no funciona para directorios, así que esto es clave para la limpieza después de mktemp -d
, por ejemplo
Reemplazar <DO CLEANUP HERE>
con CMD válida.
Una versión simplificada de respuesta de @ kevinf que parece lo suficientemente bueno para casos básicos:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(Este ejemplo es para una razón: docker-compose up
Qué dice
Cuando las salidas de comando, todos los contenedores son detenidos.
pero no rm
los contenedores dejado como docker run --rm
haría, por lo que aún se pueden ver a docker ps -a
.)
Hacer no lo soporta, pero utilizando trucos BASH se puede lograr algo similar.
default: complete
complete: do_mount
echo "Do something here..."
do_mount:
mkdir -p "$(MOUNTPOINT)"
( while ps -p $$PPID >/dev/null ; do \
sleep 1 ; \
done ; \
unmount "$(MOUNTPOINT)" \
) &
mount "$(MOUNTSOURCE)" "$(MOUNTPOINT)" -o bind
El "desmontar" se ejecutará después de que el "hacer" completa. Esto suele ser una solución satisfactoria si está intentando a las operaciones de limpieza que pueden ocurrir durante la construcción, pero no se limpian normalmente al salir "hacer".
No. Por lo que yo sé que no hay tal funcionalidad.
marca produce códigos de retorno. Por lo que puedo recordar en este momento, devuelve 0 para el éxito, el fracaso de 2 (por favor, compruebe la documentación). Por lo tanto, sería suficiente para que pueda envolver a hacer dentro de un script de shell, por ejemplo?