Ejecutar un comando con timeout

La herramienta timeout permite correr un comando con un límite de tiempo. Si el comando sigue corriendo una vez transcurrido el período de tiempo especificado como parámetro, timeout mata el proceso o le envía otra señal especificada a través de la opción -s . Este artículo demuestra algunos ejemplos de uso.







timeout , parte del paquete coreutils, puede ser útil para diferentes tareas. Por ejemplo, dejar habilitado un puerto por un determinado período de tiempo; poner un límite a una captura con tcpdump ; cerrar un programa automáticamente luego de un tiempo; etc.

Veamos un ejemplo básico con ping , más allá de que ping (al menos la versión del paquete iputils) tenga su propia opción para detener el proceso luego de cierto período de tiempo ( -w ). Normalmente se lanza ping sólo con una IP o nombre de host como parámetro y se detiene con Ctrl+C :

emi@hal9000:~$ ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=8.100 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=9.06 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=8.67 ms ^C --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 4ms rtt min/avg/max/mdev = 8.669/8.909/9.060/0.188 ms

Es posible emplear timeout para detener automáticamente el proceso luego de 5 segundos:

emi@hal9000:~$ timeout 5s ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=12.1 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=11.9 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=11.5 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=57 time=11.7 ms 64 bytes from 8.8.8.8: icmp_seq=5 ttl=57 time=11.7 ms emi@hal9000:~$

Notar que ping finaliza sin más (no muestra el resumen al finalizar). Esto se debe a diferentes señales enviadas: mientras que Ctrl+C corresponde con SIGINT (señal 2), timeout envía por defecto SIGTERM (señal 15) cuando no se especifica una como parámetro.

Es posible utilizar una señal específica a través de la opción -s . Por ejemplo, es posible enviar SIGINT en lugar de SIGTERM al alcanzar el límite de tiempo:

emi@hal9000:~$ timeout -s SIGINT 5s ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=9.81 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=8.85 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=8.80 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=57 time=8.86 ms 64 bytes from 8.8.8.8: icmp_seq=5 ttl=57 time=8.100 ms --- 8.8.8.8 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 12ms rtt min/avg/max/mdev = 8.798/9.062/9.808/0.388 ms emi@hal9000:~$

La opción -s soporta tanto el nombre como el número de señal, tal como figuran en la página de manual "signal(7)":

man signal

A su vez, timeout soporta el envío de una señal SIGKILL (señal 9) posterior, si es que el proceso no ha finalizado. Ciertas veces los procesos no responden en tiempo y forma a la señal SIGTERM o SIGINT, de esta forma es posible enviar una última señal SIGKILL para matarlos definitivamente.

Por ejemplo, el comando ping ignora a la señal SIGCONT (señales 19, 18 ó 25). Veamos un ejemplo del uso de -k (kill):

emi@hal9000:~$ timeout -s SIGCONT -k 3s 3s ping -D 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. [1582025285.142653] 64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=8.90 ms [1582025286.142781] 64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=8.76 ms [1582025287.144818] 64 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=8.90 ms [1582025288.146949] 64 bytes from 8.8.8.8: icmp_seq=4 ttl=57 time=8.98 ms [1582025289.147933] 64 bytes from 8.8.8.8: icmp_seq=5 ttl=57 time=8.84 ms [1582025290.149945] 64 bytes from 8.8.8.8: icmp_seq=6 ttl=57 time=8.86 ms Killed emi@hal9000:~$

Pasados 3 segundos ping ignora la señal SIGCONT enviada por timeout , con lo cual 3 segundos más tarde se le envía la señal SIGKILL definitiva.

Más ejemplos

timeout puede tener cientos de usos. Algunos otros que se me ocurren pueden ser capturar el tráfico de red con tcpdump durante un periodo de tiempo específico:

root@hal9000:~# timeout 10s tcpdump -i eth0 > /tmp/dump tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 92 packets captured 571 packets received by filter 179 packets dropped by kernel root@hal9000:~#

El archivo /tmp/dump de salida guarda el detalle de exactamente 10 segundos de tráfico sobre la interfaz eth0 :

root@hal9000:~# ll /tmp/dump -rw-r--r-- 1 root root 10714 Feb 18 08:34 /tmp/dump

Otro ejemplo de uso podría ser habilitar un servidor de VPN durante una hora:

# timeout 1h openvpn /etc/openvpn/server.conf

Transcurrida una hora se cierra la VPN.

Otro uso práctico sería cerrar un programa automáticamente, por ejemplo cuando se monitorea un sistema con atop :

# timeout 1m atop -f1 2

Este comando mantiene atop abierto durante 1 minuto.

Otra de las herramientas para tener a mano y conocer. Para más información sobre timeout , consultar su página de manual:

man timeout



Tal vez pueda interesarte

