bash - Proceso de matar después de un golpe de tiempo determinado?
kill (4)
¿Quiere decir que no desea que se imprima el mensaje de error si el proceso aún no se está ejecutando? Luego, simplemente podría redireccionar stderr
: kill $pid 2>/dev/null
.
También puede comprobar si el proceso todavía se está ejecutando:
if ps -p $pid >/dev/null; then kill $pid; fi
Tengo un script que intenta realizar una conexión de base de datos utilizando otro programa y el tiempo de espera (2.5min) del programa es demasiado largo. Quiero agregar esta funcionalidad al script.
Si tarda más de 5 segundos en conectarse, finalice el proceso.
Si no, mata el proceso de dormir / matar.
El problema que estoy teniendo es cómo informa bash cuando se mata un proceso, porque los procesos están en el mismo shell solo en el fondo. ¿Hay una mejor manera de hacer esto o cómo puedo silenciar la shell para los comandos kill?
DB_CONNECTION_PROGRAM > $CONNECTFILE &
pid=$!
(sleep 5; kill $pid) &
sleep_pid=$!
wait $pid
# If the DB failed to connect after 5 seconds and was killed
status=$? #Kill returns 128+n (fatal error)
if [ $status -gt 128 ]; then
no_connection="ERROR: Timeout while trying to connect to $dbserver"
else # If it connected kill the sleep and any errors collect
kill $sleep_pid
no_connection=`sed -n ''/^ERROR:/,$p'' $CONNECTFILE`
fi
Encontré este bash script timeout.sh por Anthony Thyssen ( su web ). Se ve bien.
Hay una utilidad GNU coreutils llamada timeout: http://www.gnu.org/s/coreutils/manual/html_node/timeout-invocation.html
Si lo tienes en tu plataforma, podrías hacer:
timeout 5 CONNECT_TO_DB
if [ $? -eq 124 ]; then
# Timeout occurred
else
# No hang
fi
No sé si es idéntico pero solucioné un problema similar hace unos años. Sin embargo, soy un programador, no un administrador de sistemas similar a Unix, así que tome lo siguiente con un grano de sal porque mi Bash-fu puede no ser tan fuerte ...
Básicamente hice tenedor, tenedor y tenedor:)
Sin memoria Después de recuperar mi antiguo código (que asombrosamente todavía utilizo a diario) porque mi memoria no era lo suficientemente buena, en Bash funcionó un poco como esto:
commandThatMayHang.sh 2 > /dev/null 2>&1 & (notice that last ''&'', we''re forking)
MAYBE_HUNG_PID=$!
sleepAndMaybeKill.sh $MAYBE_HUNG_PID 2 > /dev/null 2>&1 & (we''re forking again)
SLEEP_AND_MAYBE_KILL_PID=$!
wait $MAYBE_HUNG_PID > /dev/null 2>&1
if [ $? -eq 0 ]
# commandThatMayHand.sh did not hang, fine, no need to monitor it anymore
kill -9 $SLEEP_AND_MAYBE_KILL 2> /dev/null 2>&1
fi
donde sleepAndMaybeKill.sh duerme la cantidad de tiempo que deseas y luego mata a commandThatMayHand.sh .
Así que básicamente los dos escenarios son:
su comando sale bien (antes de su tiempo de espera de 5 segundos o lo que sea) y así la espera se detiene tan pronto como su comando sale bien (y mata al "asesino" porque ya no es necesario
el comando se bloquea, el asesino termina matando el comando
En cualquier caso, se le garantiza que tendrá éxito tan pronto como se ejecute el comando o que fallará después del tiempo de espera.