¿Cómo restringir el tiempo que un programa se ejecuta en Linux?

10

Tengo varias simulaciones que hacer, cada una de ellas se invoca python simulate.py <parameter list>. El problema con estas simulaciones es que algunas de ellas se cuelgan sin salir, lo que me impide ejecutarlas por lotes con un script simple.

Lo que necesitaría, es alguna forma de comando de "restricción de tiempo de ejecución", que mataría automáticamente el proceso (preferiblemente presionando virtualmente Ctrl + C , pero creo que la simple matanza también funcionará) después de un tiempo específico, si El proceso no terminó con gracia por sí mismo.

Por supuesto que puedo escribir tales guión a mí mismo, pero sospecho que alguien lo ha hecho antes que yo, así que no tengo que reinventar la rueda de pasar horas con el ps, timey los manuales de bash.

Adam Ryczkowski
fuente

Respuestas:

15

Posible solución # 1

Usa el timeoutcomando:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

Puede poner una guardia en el timeoutcomando también en killel proceso si no se ha detenido después de un período de tiempo también.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

Esto esperará hasta 20 segundos después de que el proceso sleep 100debería haberse detenido; si aún se está ejecutando, timeoutle enviará una killseñal.

Posible solución # 2

Una forma alternativa, aunque el método más arriesgado sería el siguiente:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Encontré esta técnica en Stack Overflow en una pregunta titulada: Limitar el tiempo que un programa se ejecuta en Linux . Específicamente esta respuesta .

NOTA: Según un comentario dejado por @mattdm, el método anterior puede ser riesgoso dado que supone que no se han iniciado nuevos procesos desde su proceso. Por lo tanto, no se han asignado nuevos PID. Dado esto, este enfoque probablemente no debería usarse, pero aquí solo sirve como referencia para un enfoque general del problema. El timeoutmétodo es la mejor opción del 2.

slm
fuente
Pero entonces se garantizará que el guión siempre tomará todo ese tiempo. En mi caso, no es 1 segundo, sino 15 minutos.
Adam Ryczkowski
Pero la otra solución encontrada en esa pregunta debería ser precisamente lo que necesito. ¡Gracias!
Adam Ryczkowski
2
Suponga que myProgram termina en menos tiempo que sleep(no es una suposición irracional ya que el objetivo es establecer un tiempo de ejecución máximo permitido). Luego envía una señal a un PID inexistente (sin daño real) o a cualquier proceso aleatorio en el sistema (potencialmente fatal).
un CVn
1
@ MichaelKjörling, gracias por la respuesta. He actualizado mi respuesta por el mismo comentario que el OP dejó también. Parece que el timeoutcomando hace exactamente lo que está buscando, esperando que el OP responda a mis comentarios.
slm
@slm timeoutdebería ser la solución que necesito. Lo estoy probando en este momento
Adam Ryczkowski,
4

He encontrado algo un poco mejor, que timeout: timelimit.

Tiene varias ventajas; uno es que el usuario puede abortar manualmente la ejecución presionando "Ctrl + C".

El timelimitprograma está disponible en el repositorio de Debian.

Adam Ryczkowski
fuente
1
Tratando de entender las diferencias en tiempo y límite de tiempo en blanco y negro. el tiempo de espera se puede detener con Ctrl + C. ¿Cuáles son las otras ventajas?
slm
Bueno, mi tiempo de espera no puede. Yo uso Mint 14 (basado en Ubuntu Quantal).
Adam Ryczkowski
3

Puede ajustar el tiempo de CPU y otras cosas con ulimit, especialmente para el tiempo de CPU:

$ ulimit -t 60      # limit to 60 seconds
$ program
RSFalcon7
fuente
Vea estas preguntas y respuestas de U&L: unix.stackexchange.com/a/4666/7453 . @Gilles ofrece una buena descripción del uso de ulimit para este propósito.
slm
0

Bash usa una variable llamada $BASHPIDque se puede usar en tal situación, por ejemplo:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

Puede cambiar el argumento en la llamada a sleepin do_face()en 100lugar de 10y ver qué sucede cuando el niño tarda demasiado en hacer sus tareas. Simplemente cambie la llamada para dormir en do_face()una llamada a su ejecutable y si tarda demasiado, la secuencia de comandos la matará, 20en este ejemplo , segundos es el valor límite. Los parámetros se pueden implementar para que esto se convierta en un script simple para llamar y pueda ser llamado por otro script en lote o lo que sea. El manejo de los archivos pid para cada proceso concurrente es un problema que deberá ser manejado, quizás use diferentes subdirectorios ...

NB: en GNU Linux sleeppuede tomar argumentos de coma flotante, como sleep 0.1dormir durante una décima de segundo.

Overloaded_Operator
fuente