Tuer le processus avec une utilisation élevée du processeur après X fois? [fermé]

21

Sous Linux, j'ai quelques processus qui ont tendance à planter occasionnellement (serveurs de jeux), qui finissent par utiliser 100% de processeur.

Je cherche un programme ou un script pour vérifier l'utilisation du processeur d'une liste de processus par nom et s'ils sont à 100% pendant plus de X fois, disons 30 secondes, tuez-les. J'ai essayé ps-watcher mais je n'ai pas pu déterminer comment y parvenir.

Le simple fait de tuer le processus à 100% d'utilisation ne fonctionnera pas, car il le frappera pendant de brèves périodes pendant le fonctionnement normal.

J'ai également trouvé ce script qui semble faire ce que je veux, mais il est limité à un seul processus: lien

Toute aide est grandement appréciée!

user30153
la source
Pouvez-vous s'il vous plaît poster à nouveau un lien vers le script car celui-ci pastebin.com/m1c814cb4 ne semble plus être valide.
Aurais-je raison de penser que vous utilisez des serveurs Minecraft? ;)
PhonicUK
@Chris S Vous êtes terne. C'est une question très intéressante. Pouvez-vous fournir une source pour vos réclamations "car elles attirent des réponses de mauvaise qualité, d'opinion et de spam, et les réponses deviennent rapidement obsolètes."? Et pouvez-vous donner quelques exemples de la manière dont les réponses existantes à cette question sont à la hauteur? Je ne retiens pas mon souffle.
db

Réponses:

19

Essayez monit .

Vous pouvez utiliser une configuration comme celle-ci pour accomplir votre tâche:

check process gameserver with pidfile /var/run/gameserver.pid
  start program = "/etc/init.d/gameserver start" with timeout 60 seconds
  stop program  = "/etc/init.d/gameserver stop"
  if cpu > 80% for 2 cycles then alert
  if cpu > 95% for 5 cycles then restart
  if totalmem > 200.0 MB for 5 cycles then restart
  if loadavg(5min) greater than 10 for 8 cycles then stop
  if failed port 12345 type tcp with timeout 15 seconds
    then restart
  if 3 restarts within 5 cycles then timeout

Les détails sur cette configuration peuvent être trouvés dans la documentation de monit .

joschi
la source
Merci pour la réponse! Existe-t-il un moyen de surveiller le processus sans avoir à le démarrer avec monit? J'ai une tonne de serveurs fonctionnant sur la machine qui sont gérés via une interface Web, devoir les lancer avec monit n'est pas idéal.
user30153
Bien sûr, les lignes start programet stop programsont juste pour le cas où monitvous avez besoin de redémarrer votre processus. Vous pouvez toujours le démarrer avec votre script d'initialisation normal. monitpeut également vérifier si le programme est déjà en cours d'exécution (par exemple par son fichier PID ou son nom de processus).
joschi
Fantastique, je pense que j'ai compris. Le seul problème est sa dépendance à un fichier pid, je vais devoir en générer un pour plus de 200 processus et créer des règles pour chacun, je suppose. Merci pour l'aide!
user30153
4

C'est ce que je cherchais, et je l'utilise depuis un certain temps (légèrement modifié). Dernièrement, j'ai mis un bogue dans mon travail, mais je dois continuer à faire fonctionner l'application (serveur de jeu).
J'avais cité la partie où le PID le plus élevé est tué, car il tuait le mauvais PID.
Voici ma dernière ébauche de votre script, jusqu'à présent, il trouve la surcharge la plus élevée et la tue efficacement (m'envoie également des informations chaque fois qu'il fait quoi que ce soit);

#!/bin/bash

## Note: will kill the top-most process if the $CPU_LOAD is greater than the $CPU_THRESHOLD.
echo
echo checking for run-away process ...

CPU_LOAD=$(uptime | cut -d"," -f4 | cut -d":" -f2 | cut -d" " -f2 | sed -e "s/\.//g")
CPU_THRESHOLD=300
PROCESS=$(ps aux r)
TOPPROCESS=$(ps -eo pid -eo pcpu -eo command | sort -k 2 -r | grep -v PID | head -n 1)

if [ $CPU_LOAD -gt $CPU_THRESHOLD ] ; then
  # kill -9 $(ps -eo pid | sort -k 1 -r | grep -v PID | head -n 1) #original
  # kill -9 $(ps -eo pcpu | sort -k 1 -r | grep -v %CPU | head -n 1)
  kill -9 $TOPPROCESS
  echo system overloading!
  echo Top-most process killed $TOPPROCESS
  echo load average is at $CPU_LOAD
  echo 
  echo Active processes...
  ps aux r

  # send an email using mail
  SUBJECT="Runaway Process Report at Marysol"
  # Email To ?
  EMAIL="[email protected]"
  # Email text/message
  EMAILMESSAGE="/tmp/emailmessage.txt"
  echo "System overloading, possible runaway process."> $EMAILMESSAGE
  echo "Top-most process killed $TOPPROCESS" >>$EMAILMESSAGE
  echo "Load average was at $CPU_LOAD" >>$EMAILMESSAGE
  echo "Active processes..." >>$EMAILMESSAGE
  echo "$PROCESS" >>$EMAILMESSAGE
  mail -s "$SUBJECT" "$EMAIL" < $EMAILMESSAGE

else
 echo
 echo no run-aways. 
 echo load average is at $CPU_LOAD
 echo 
 echo Active processes...
 ps aux r
fi
exit 0


Ce petit script a été extrêmement utile, si vous n'aimez pas qu'il tue un processus, l'e-mail vous aidera à vous tenir informé.

Angelo Felix
la source
Merci pour votre réponse! Je voudrais simplement souligner que votre tri TOPPROCESSest désactivé. Il ne triera pas par valeur réelle, mais ordonnera les entrées par ordre alphanumérique (par exemple, 6% auront priorité sur 12%). Une meilleure alternative pourrait être la commande suivante:top -b -n 1 | sed 1,6d | sed -n 2p
Glutanimate
1
Si le CPU est à 90%, quel est le CPU_LOAD? et comment calculez-vous le seuil? merci
Ofir Attia
1
Cela n'attrapera pas les situations où un processus est au maximum sur un serveur multicœur.
UpTheCreek
0

Vous trouverez ci-dessous un exemple de script BASH qui peut vous aider à obtenir des conseils pour vos propres besoins.

#!/bin/bash

CPU_LOAD=$(uptime | cut -d"," -f4 | cut -d":" -f2 | cut -d" " -f2 | sed -e "s/\.//g")
CPU_THRESHOLD=700

if [ $CPU_LOAD -gt $CPU_THRESHOLD ] ; then
  kill -9 $(ps -eo pid | sort -k 1 -r | grep -v PID | head -n 1)
fi

exit 0

Veuillez noter que la valeur de votre $ CPU_THRESHOLD devrait dépendre du nombre de cœurs (CPU) que vous avez sur votre système. Une explication détaillée sur ce sujet peut être trouvée à http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages .

Vous pouvez appeler votre script depuis l'intérieur de / etc / inittab ou un cronjob pour chaque nombre de minutes que vous préférez. Veuillez également noter que l'exemple de script tuera le processus le plus élevé si $ CPU_LOAD est supérieur à $ CPU_THRESHOLD.

bintut
la source