Tuez tous les processus en cours d'exécution pendant plus de 5 minutes par un utilisateur donné dans le script bash linux

18

J'ai besoin de la commande pour tuer les processus en cours d'exécution depuis au moins 5 minutes pour un processus donné.

Je devrai exécuter cette commande toutes les cinq minutes environ.

Mille mercis !

(le système est Centos5)


la source

Réponses:

17
kill -9 $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print $2}}')

où "procname" est un nom de processus et 300 est le seuil de temps d'exécution

Chapeau blanc
la source
Excellent oneliner. Je l'ai utilisé sans -9être un peu plus convivial pour mes processus et j'ai ajouté un grep -v defunct |avant awkcomme autre chose que vous pouvez voir procname <defunct>dans votre sortie, ce qui empêcherait la commande awk de renvoyer un PID valide. Et cela casserait la commande kill.
Michael Härtl
je dirais que $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')c'est un peu plus fluide mais la réponse est quand même super
Yevgen
@WhiteHat comment ferait la même chose sans un processus avec certains pid?
Petar Vasilev
une chose m'a fait perdre mon temps: devrait utiliser 'with awk NOT "
cn123h
6

Peut-être exécuter la commande longue comme celle-ci dans une crontab?

timeout -k 300 command
atx
la source
5

Ma version de kill script, tirant parti des deux réponses précédentes:

#!/bin/bash

#Email to send report
MY_EMAIL="[email protected]"

#Process name to kill
NAME_KILL="php"

#UID to kill
UID_KILL=33.

#Time in seconds which the process is allowed to run
KILL_TIME=60

KILL_LIST=()
EMAIL_LIST=()
while read PROC_UID PROC_PID PROC_ETIMES PROC_ETIME PROC_COMM PROC_ARGS; do
    if [ $PROC_UID -eq $UID_KILL -a "$PROC_COMM" == "$NAME_KILL" -a $PROC_ETIMES -gt $KILL_TIME ]; then
    KILL_LIST+=("$PROC_PID");
    MSG="Killing '$PROC_ARGS' which runs for $PROC_ETIME";
    EMAIL_LIST+=("$MSG");
    echo "$MSG";
    fi
done < <(ps eaxo uid,pid,etimes,etime,comm,args | tail -n+2)
if [ ${#KILL_LIST[*]} -gt 0 ]; then
    kill -9 ${KILL_LIST[@]}
    printf '%s\n' "${EMAIL_LIST[@]}" | mail -s "Long running processes killed" $MY_EMAIL
fi

Il filtre le processus par UID, NAME et si le temps d'exécution dépasse la limite - tue les processus et envoie le rapport par e-mail. Si vous n'avez pas besoin de cet e-mail, vous pouvez simplement commenter la dernière ligne.

Viperet
la source
2

J'ai trouvé la solution sur cette page: http://www.directadmin.com/forum/showthread.php?t=26179

Créez un fichier vide et appelez-le killlongproc.sh

Copiez ceci:

#!/bin/bash
# This script will kill process which running more than X hours
# egrep: the selected process; grep: hours
PIDS="`ps eaxo bsdtime,pid,comm | egrep "spamd|exim|mysqld|httpd" | grep " 1:" | awk '{print $2}'`"

# Kill the process
echo "Killing spamd, exim, mysqld and httpd processes running more than one hour..."
for i in ${PIDS}; do { echo "Killing $i"; kill -9 $i; }; done;

Arrête ça dans ton cronjob

15 * * * * * root /{directory}/./killongproc.sh
En pause jusqu'à nouvel ordre.
la source
4
C'est généralement une mauvaise idée de le faire. Quel problème essayez-vous vraiment de résoudre? De plus, vous ne devez pas l'utiliser kill -9car cela ne donne pas aux processus la possibilité d'effectuer un nettoyage en douceur avant de quitter.
pause jusqu'à nouvel ordre.
1
Cela tue les processus qui ont consommé une certaine quantité de temps CPU (utilisateur + système), pas les processus qui s'exécutent pendant une certaine quantité de temps réel (par exemple démarré avant 1 heure).
Marki555
2

Il y a ici un script que vous pouvez modifier pour faire ce que vous voulez.

EDIT a ajouté le script ci-dessous

#!/bin/bash
#
#Put the UID to kill on the next line
UID_KILL=1001

#Put the time in seconds which the process is allowed to run below
KILL_TIME=300

KILL_LIST=`{
ps -eo uid,pid,lstart | tail -n+2 |
    while read PROC_UID PROC_PID PROC_LSTART; do
        SECONDS=$[$(date +%s) - $(date -d"$PROC_LSTART" +%s)]
        if [ $PROC_UID -eq $UID_KILL -a $SECONDS -gt $KILL_TIME ]; then
        echo -n "$PROC_PID "
        fi
     done 
}`

if [[ -n $KILL_LIST ]]
then
        kill $KILL_LIST
fi
Le temps est venu
la source
Je n'ai pas assez de connaissances pour le modifier, c'est pourquoi je vous demande
2
Trop compliqué. Vous pouvez utiliser la colonne etimesde pspour vous montrer directement les secondes écoulées depuis le démarrage du processus (pas besoin de le calculer à partir de l'heure de début).
Marki555
@ Marki555 oui c'est vrai. Cependant, sur les systèmes dont les versions psne prennent pas en charge etimes(uniquement etime), c'est une excellente alternative. Je viens d' utiliser quand la réponse haut m'a donné une erreur deps
mike
0

J'ai dû résoudre une tâche similaire, et elle n'a pas besoin de script. Pour terminer (signal SIGTERM) les processus de l'exécutable "THECOMMAND":

killall -u $USER --older-than 5m THECOMMAND

La restriction à l'utilisateur actuel -u $USERn'est nécessaire que pour éviter les messages d'erreur inutiles si d'autres utilisateurs exécutent également "THECOMMAND". Dans votre propre crontab utilisateur, vous devez saisir les informations suivantes:

*/5 * * * *     killall -u $USER --older-than 5m THECOMMAND

Dans une crontab système (utilisateur 'root'), vous ajouteriez ce qui suit:

*/5 * * * *     killall --older-than 5m THECOMMAND

Si vous voulez tuer (SIGKILL) les processus au lieu de les terminer (SIGTERM), envoyez explicitement le signal SIGKILL en ajoutant --signal SIGKILLaux paramètres. Exemple pour un système crontab:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND
t0r0X
la source
-4

Pour httpd

ps eaxo pid, temps, comm | queue -n + 2 | grep 'httpd' | awk 'substr (0,9,1 $)> 0' | awk '{print $ 1}'

puremind
la source