Tue automatiquement un processus s'il dépasse une quantité donnée de RAM

12

Je travaille sur des jeux de données à grande échelle. Lors du test d'un nouveau logiciel, un script se glisse parfois sur moi, récupère rapidement toute la RAM disponible et rend mon bureau inutilisable. Je voudrais un moyen de définir une limite de RAM pour un processus afin que s'il dépasse ce montant, il soit automatiquement tué. Une solution spécifique au langage ne fonctionnera probablement pas, car j'utilise toutes sortes d'outils différents (R, Perl, Python, Bash, etc.).

Existe-t-il une sorte de moniteur de processus qui me permettra de définir un seuil de RAM et de tuer automatiquement un processus s'il en utilise plus?

chrisamiller
la source
@ Uri: À ce sujet, je n'ai obtenu qu'une réponse partielle (uniquement pour la partie cpu de ma question) - et pas optimale. Il pose des questions sur l'utilisation de la RAM.
Chriskin
1
Uri, il y a un manque total d'idées utiles dans ce fil. La publication d'un lien vers celui-ci n'est pas particulièrement utile.
chrisamiller
1
Hrmm - ce fil de superutilisateur semble avoir une suggestion raisonnable en utilisant ulimit: superuser.com/questions/66383/restrict-ram-for-user-or-process
chrisamiller

Réponses:

11

Je déteste être le gars qui répond à sa propre question, mais ce matin, j'ai trouvé une méthode alternative, enveloppée dans un joli petit utilitaire. Cela limitera le temps CPU ou la consommation de mémoire:

https://github.com/pshved/timeout

Je donne un coup de feu à celui-ci en premier, mais vote à Amey Jah pour la bonne réponse. Je vais vérifier si celui-ci me fait défaut.

chrisamiller
la source
5
+1 Répondre à votre propre question est OK !
Tom Brossman
10

Je conseillerais fortement de ne pas le faire . Comme suggéré par @chrisamiller, définir ulimit limitera la RAM disponible avec le processus.

Mais si vous insistez, suivez cette procédure.

  1. Enregistrez le script suivant sous 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. Rendez-le maintenant exécutable.

    chmod +x killif.sh
    
  3. Exécutez maintenant ce script sur le terminal. Remplacez PROCIDpar l'ID de processus réel et SIZEpar la taille en Mo.

    ./killif.sh PROCID SIZE
    

    Par exemple:

    ./killif.sh 132451 100
    

    Si la valeur SIZEest 100, le processus sera tué si son utilisation de la RAM dépasse 100 Mo.

Attention: vous savez ce que vous essayez de faire. Tuer n'est pas une bonne idée. Si ce processus a une commande d'arrêt ou d'arrêt, modifiez le script et remplacez la kill -9commande par cette shutdowncommande.

Amey Jah
la source
j'envisagerais d'
@George Edison Comment avez-vous fait cela. Lorsque j'ai essayé de coller, cela me donnait un texte étrangement formaté. Denwerko: Où aimeriez-vous dormir. J'ai déjà mis 10 secondes de sommeil dans la boucle while
Amey Jah
2
Merci pour la solution, comme indiqué ci-dessous, je peux la vérifier. Pourquoi tous ces avertissements terribles sur les processus de mise à mort? Le logiciel de gestion de cluster (LSF, PBS, et al) le fait tout le temps lorsqu'un processus dépasse la quantité de ressources qu'il a demandée, sans conséquences désastreuses. Je suis d'accord que ce n'est pas une bonne solution pour les nouveaux utilisateurs qui risquent de mal l'appliquer, mais dans les bonnes circonstances, cela peut être très utile.
chrisamiller
@chrisamiller J'ai lancé un avertissement aux futurs lecteurs. Dans votre cas, vous connaissez les implications mais le futur lecteur de cet article pourrait ne pas être au courant de telles implications.
Amey Jah
2
Pouvez-vous expliquer pourquoi ne pas le faire?
jterm
2

Essayez l' prlimitoutil, à partir du util-linuxpackage. Il exécute un programme avec des limites de ressources. Il utilise l' prlimitappel système pour définir les limites, qui sont ensuite appliquées uniquement par le noyau.

Vous pouvez configurer 16 limites, notamment:

  • quantité maximale de temps processeur en secondes
  • nombre maximum de processus utilisateur
  • taille maximale de l'ensemble résident ("mémoire utilisée")
  • taille maximale qu'un processus peut verrouiller en mémoire
  • taille de la mémoire virtuelle
  • nombre maximum de fichiers ouverts
  • nombre maximum de verrous de fichiers
  • nombre maximum de signaux en attente
  • octets maximum dans les files d'attente de messages POSIX
Bram Geron
la source
0

C'était trop gros pour contenir un commentaire. J'ai modifié le script d'origine d'Amey pour inclure un pgrep, donc au lieu d'avoir à saisir manuellement l'ID du processus, vous pouvez simplement l'exclure par son nom. Par exemple, ./killIf.sh chrome 4000tue tout processus Chrome qui dépasse 4 Go en mémoire.

#!/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

Veillez à sélectionner une chaîne grep étroite et une limite de mémoire suffisamment grande pour ne pas tuer inutilement les processus involontaires.

Gaurang Tandon
la source