Las traps son un modo de interceptar señales en Linux de este modo podemos ejecutar una acción determinada al recibir una señal en concreto. Esto nos permitirá escribir scripts con funcionalidades avanzadas y una mejor gestión de errores.
Para ver la lista de señales disponibles ejecutamos:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
Pongamos como ejemplo que cuando se presione Ctrl+c querremos que se ejecute el comando uname -a, Ctrl+c es la señal SIGINT(2):
Presionamos Ctrl+c y efectivamente se ejecuta el comando deseado:
^CLinux RX4 4.19.44-gentoo-kr0m-AMDGPU-YAMA-ACM-appArmor-KProbes-Docker #3 SMP PREEMPT Thu Jun 6 22:48:45 CEST 2019 x86_64 Intel(R) Core(TM) i3-4170 CPU @ 3.70GHz GenuineIntel GNU/Linux
Ahora pongamos un script el cual creará el fichero /tmp/yy cuando reciba la señal SIGUSR1(10):
#!/bin/bash
trap 'touch /tmp/yy' 10
while true; do
sleep 1
done
Le damos permisos de ejecución:
Ejecutamos el script:
Comprobamos que el fichero no existe:
ls: no se puede acceder a '/tmp/yy': No existe el fichero o el directorio
Localizamos el PID del script:
kr0m 9663 0.0 0.0 12576 3192 pts/7 S+ 22:50 0:00 /bin/bash ./test.sh
Le enviamos la señal SIGUSR1(10):
Comprobamos que se ha creado el fichero:
-rw-r--r-- 1 kr0m kr0m 0 jun 19 22:51 /tmp/yy
Otro uso muy útil es la gestión de errores:
#!/bin/bash
err_report() {
echo "Error detected"
}
trap 'err_report' ERR
ls $1
Este script ejecutará la función err_report cuando se produzca un error.
Cuando le pasamos como argumento un fichero existente, hace un ls de este:
/tmp/yy
Si lo ejecutamos con uno inexistente, ejecuta la función de error:
ls: no se puede acceder a '/tmp/y': No existe el fichero o el directorio
Error detected
También puede resultarnos de utilidad para hacer limpieza de ficheros temporales en caso de que el script falle.