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)


quelle

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

Weißer Hut
quelle
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
atx
quelle
5

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

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

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.

Viperet
quelle
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
Bis auf weiteres angehalten.
quelle
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
Die Zeit ist gekommen
quelle
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
t0r0X
quelle
-4

Für httpd

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

Reiner Geist
quelle