Beenden Sie alle Prozesse, die von einem bestimmten Benutzer im Linux-Bash-Skript länger als 5 Minuten ausgeführt werden


18

Ich benötige den Befehl, um Prozesse abzubrechen, die seit mindestens 5 Minuten für einen bestimmten Prozess ausgeführt wurden.

Ich muss diesen Befehl etwa alle fünf Minuten ausführen.

Tausend Dank !

(System ist Centos5)

linux  bash 

Antworten:


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

Dabei ist "Prozessname" ein Prozessname und 300 der Schwellenwert für die Laufzeit


Großartiger Oneliner. Ich habe es verwendet, ohne -9ein wenig freundlicher mit meinen Prozessen umzugehen , und ein grep -v defunct |Vorher hinzugefügt, awkwie Sie vielleicht procname <defunct>in Ihrer Ausgabe sehen, was dazu führen würde, dass der Befehl awk keine gültige PID zurückgibt . Und das würde den Kill-Befehl brechen.
— Michael Härtl

Ich würde sagen, es $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')ist ein bisschen flüssiger, aber die Antwort ist trotzdem großartig
— Jewgen

@WhiteHat wie würde das gleiche aber für einen Prozess mit bestimmten pid tun?
— Petar Vasilev

Eine Sache, die meine Zeit verschwendet hat, ist, dass ich "mit awk NOT" verwenden sollte
— cn123h

6

Führen Sie den Langzeitbefehl wie folgt in einer Crontab aus?

timeout -k 300 command

5

Meine Version des Kill-Skripts nutzt die beiden vorherigen Antworten:

#!/bin/bash

#Email to send report
MY_EMAIL="example@email.com"

#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

Es filtert den Prozess nach UID, NAME und wenn die Ausführungszeit das Limit überschreitet, werden Prozesse abgebrochen und Berichte an E-Mails gesendet. Wenn Sie diese E-Mail nicht benötigen, können Sie einfach die letzte Zeile kommentieren.


2

Ich habe die Lösung auf dieser Seite gefunden: http://www.directadmin.com/forum/showthread.php?t=26179

Machen Sie eine leere Datei und nennen Sie sie killlongproc.sh

Kopier das:

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

Hör auf damit in deinem Cronjob

15 * * * * * root /{directory}/./killongproc.sh

4
Es ist normalerweise eine schlechte Idee, dies zu tun. Welches Problem versuchen Sie wirklich zu lösen? Sie sollten es auch nicht verwenden, kill -9da es Prozessen nicht die Möglichkeit gibt, vor dem Beenden eine ordnungsgemäße Bereinigung durchzuführen.
— Bis auf weiteres angehalten.

1
Dies beendet Prozesse, die etwas CPU-Zeit in Anspruch genommen haben (Benutzer + System), nicht Prozesse, die eine gewisse Zeit in Echtzeit ausgeführt werden (z. B. vor 1 Stunde gestartet).
— Marki555

2

Hier gibt es ein Skript , das Sie ändern können, um das zu tun, was Sie wollen.

EDIT hat das folgende Skript hinzugefügt

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

Ich habe nicht genug Wissen, um es zu ändern, deshalb frage ich Sie

2
Zu kompliziert. Sie können die Spalte etimesvon verwenden ps, um die seit dem Prozessstart verstrichenen Sekunden direkt anzuzeigen (es ist nicht erforderlich, sie von der Startzeit an zu berechnen).
— Marki555

@ Marki555 ja das stimmt. Auf Systemen mit (nur ) psnicht unterstützten Versionen ist dies jedoch eine großartige Alternative. Ich habe es gerade benutzt, als mir die beste Antwort einen Fehler vonetimesetimeps
— mike

0

Ich musste eine ähnliche Aufgabe lösen und es wird kein Skript benötigt. Zum Beenden (Signalisieren von SIGTERM) von Prozessen der ausführbaren Datei "THECOMMAND":

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

Die Beschränkung auf den aktuellen Benutzer -u $USERist nur erforderlich, um unnötige Fehlermeldungen zu vermeiden, wenn andere Benutzer ebenfalls "THECOMMAND" ausführen. In Ihrem eigenen Benutzer crontab würden Sie Folgendes eingeben:

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

In einer System-Crontab (Benutzer 'root') würden Sie Folgendes hinzufügen:

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

Wenn Sie die Prozesse beenden (SIGKILL) möchten, anstatt sie zu beenden (SIGTERM), senden Sie das SIGKILL-Signal explizit durch Hinzufügen --signal SIGKILLzu den Parametern. Beispiel für eine System-Crontab:

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

-4

Für httpd

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.