Eliminar automáticamente un proceso si excede una cantidad dada de RAM

12

Trabajo en conjuntos de datos a gran escala. Al probar un nuevo software, algunas veces un script se me escapa, toma rápidamente toda la RAM disponible y deja mi escritorio inutilizable. Me gustaría una forma de establecer un límite de RAM para un proceso para que si excede esa cantidad, se eliminará automáticamente. Una solución específica del idioma probablemente no funcionará, ya que utilizo todo tipo de herramientas diferentes (R, Perl, Python, Bash, etc.).

Entonces, ¿hay algún tipo de monitor de proceso que me permita establecer una cantidad umbral de RAM y eliminar automáticamente un proceso si usa más?

Chrisamiller
fuente
@ Uri: en ese hilo solo obtuve una respuesta parcial (solo para la parte de la CPU de mi pregunta), y no óptima. Pregunta sobre el uso de RAM.
Chriskin
1
Uri, hay una falta total de ideas útiles en ese hilo. Publicar un enlace no es particularmente útil.
Chrisrisler
1
Hrmm - este hilo superusuario parece tener una sugerencia razonable utilizando ulimit: superuser.com/questions/66383/restrict-ram-for-user-or-process
chrisamiller

Respuestas:

11

Odio ser el tipo que responde a su propia pregunta, pero esta mañana encontré un método alternativo, envuelto en una pequeña y agradable utilidad. Limitará el tiempo de CPU o el consumo de memoria:

https://github.com/pshved/timeout

Primero le doy una oportunidad a este, pero vota a Amey Jah por la buena respuesta. Lo comprobaré si este me falla.

Chrisamiller
fuente
55
+1 ¡Responder a tu propia pregunta está bien !
Tom Brossman
10

Recomiendo encarecidamente que no lo haga . Según lo sugerido por @chrisamiller, la configuración de ulimit limitará la RAM disponible con el proceso.

Pero aún así, si insiste, siga este procedimiento.

  1. Guarde el siguiente script como killif.sh:

    #!/bin/sh
    
    if [ $# -ne 2 ];
    then
        echo "Invalid number of arguments"
        exit 0
    fi
    
    while true;
    do
        SIZE=$(pmap $1|grep total|grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id =$1 Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$1"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    
        sleep 10
    done
  2. Ahora hazlo ejecutable.

    chmod +x killif.sh
    
  3. Ahora ejecute este script en la terminal. Reemplace PROCIDcon la identificación del proceso real y SIZEcon el tamaño en MB.

    ./killif.sh PROCID SIZE
    

    Por ejemplo:

    ./killif.sh 132451 100
    

    Si SIZEes 100, el proceso se eliminará si su uso de RAM supera los 100 MB.

Precaución: sabes lo que estás tratando de hacer. El proceso de matar no es una buena idea. Si ese proceso tiene algún comando de apagado o detención, edite el script y reemplace el kill -9comando con ese shutdowncomando.

Amey Jah
fuente
consideraría dormir un poco allí, por ejemplo dormir 0.5 ...
Denwerko
@ George Edison ¿Cómo hiciste eso? Cuando intenté pegar, me estaba dando texto con un formato extraño. Denwerko: ¿Dónde te gustaría dormir? Ya he dormido 10 segundos en el ciclo while
Amey Jah
2
Gracias por la solución, como se indica a continuación, puedo comprobarlo. Sin embargo, ¿por qué todas las terribles advertencias sobre los procesos de asesinato? El software de administración de clústeres (LSF, PBS, et al) hace esto todo el tiempo cuando un proceso excede la cantidad de recursos que solicitó, sin consecuencias nefastas. Estoy de acuerdo en que esta no es una buena solución para los nuevos usuarios que puedan aplicarla incorrectamente, pero en las circunstancias correctas, esto puede ser bastante útil.
Chrisrisler
@chrisamiller He puesto una advertencia para futuros lectores. En su caso, conoce las implicaciones, pero el futuro lector de esta publicación podría no ser consciente de tales implicaciones.
Amey Jah
2
¿Puedes explicar por qué no hacerlo?
jterm
2

Prueba la prlimitherramienta, desdeutil-linux paquete. Ejecuta un programa con límites de recursos. Utiliza la prlimitllamada del sistema para establecer los límites, que luego son aplicados exclusivamente por el núcleo.

Puede configurar 16 límites, que incluyen:

  • cantidad máxima de tiempo de CPU en segundos
  • número máximo de procesos de usuario
  • tamaño máximo del conjunto residente ("memoria usada")
  • tamaño máximo que un proceso puede bloquear en la memoria
  • tamaño de la memoria virtual
  • cantidad máxima de archivos abiertos
  • número máximo de bloqueos de archivo
  • número máximo de señales pendientes
  • bytes máximos en colas de mensajes POSIX
Bram Geron
fuente
0

Esto era demasiado grande para un comentario. Modifiqué el script original de Amey para incluir a pgrep, por lo que en lugar de tener que ingresar manualmente la identificación del proceso, puede excluir por nombre. Por ejemplo, ./killIf.sh chrome 4000mata cualquier proceso de Chrome que exceda los 4 GB en uso de memoria.

#!/bin/sh

# $1 is process name
# $2 is memory limit in MB

if [ $# -ne 2 ];
then
    echo "Invalid number of arguments"
    exit 0
fi

while true;
do
    pgrep "$1" | while read -r procId;
    do
        SIZE=$(pmap $procId | grep total | grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id = $procId Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$procId"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    done

    sleep 1
done

Tenga cuidado de seleccionar una cadena grep estrecha y un límite de memoria lo suficientemente grande como para no matar innecesariamente procesos no deseados.

Gaurang Tandon
fuente