Zabij wszystkie procesy uruchomione przez danego użytkownika przez ponad 5 minut w skrypcie bash dla systemu Linux

18

Potrzebuję polecenia, aby zabić procesy, które działały od co najmniej 5 minut dla danego procesu.

Będę musiał uruchamiać to polecenie co około pięć minut.

Stukrotne dzięki !

(system to Centos5)


źródło

Odpowiedzi:

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

gdzie „procname” to nazwa procesu, a 300 to próg czasu działania

Biały kapelusz
źródło
Świetny oneliner. Użyłem go, -9żeby nie być trochę bardziej przyjaznym dla moich procesów, i dodałem grep -v defunct |wcześniej, awkjak inaczej widać procname <defunct>na wyjściu, co sprawiłoby, że polecenie awk nie zwróciłoby prawidłowego PID. A to złamałoby polecenie zabicia.
Michael Härtl
powiedziałbym, że $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')jest nieco gładszy, ale odpowiedź i tak jest świetna
Yevgen
@ WhiteHat jak zrobiłby to samo, gdyby nie proces z pewnym pid?
Petar Vasilev
jedna rzecz zmarnowała mi czas: należy używać „z awk NOT”
cn123h
6

Może uruchom tak długo uruchomioną komendę w crontab?

timeout -k 300 command
atx
źródło
5

Moja wersja skryptu zabijania, wykorzystująca obie poprzednie odpowiedzi:

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

Filtruje proces według UID, NAZWA, a jeśli czas wykonania przekroczy limit - zabija procesy i wysyła raport na e-mail. Jeśli nie potrzebujesz tego e-maila - możesz po prostu skomentować ostatni wiersz.

Viperet
źródło
2

Znalazłem rozwiązanie na tej stronie: http://www.directadmin.com/forum/showthread.php?t=26179

Utwórz pusty plik i nazwij go killlongproc.sh

Skopiuj to:

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

Zatrzymaj to w swojej koleżance

15 * * * * * root /{directory}/./killongproc.sh
Wstrzymano do odwołania.
źródło
4
Zazwyczaj jest to zły pomysł. Jaki problem naprawdę próbujesz rozwiązać? Ponadto nie powinieneś używać, kill -9ponieważ nie daje procesom szansy na płynne czyszczenie przed wyjściem.
Wstrzymano do odwołania.
1
Zabija to procesy, które pochłonęły pewien czas procesora (użytkownik + system), a nie procesy działające przez pewien czas w czasie rzeczywistym (np. Rozpoczęte przed 1 godziną).
Marki555
2

Jest tutaj skrypt , który możesz zmodyfikować, aby zrobić to, co chcesz.

EDIT dodał poniższy skrypt

#!/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
czas
źródło
Nie mam wystarczającej wiedzy, aby to zmienić, dlatego proszę Cię
2
Zbyt skomplikowane. Możesz użyć kolumny etimeslub, psaby wyświetlić bezpośrednio upływające sekundy od rozpoczęcia procesu (nie musisz obliczać go od czasu rozpoczęcia).
Marki555
@ Marki555 tak, to prawda. Jednak w systemach z wersjami ps, które nie obsługują etimes(tylko etime), jest to świetna alternatywa. Właśnie go użyłem, gdy pierwsza odpowiedź dała mi błądps
mike
0

Musiałem rozwiązać podobne zadanie i nie potrzebuje on skryptu. Do kończenia procesów (sygnał SIGTERM) wykonywalnego „THECOMMAND”:

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

Ograniczenie do bieżącego użytkownika -u $USERjest konieczne tylko w celu uniknięcia niepotrzebnych komunikatów o błędach, jeśli inni użytkownicy również uruchamiają „THECOMMAND”. We własnym crontabie użytkownika wpisujesz następujące dane:

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

W systemowym pliku crontab (użytkownik „root”) należy dodać:

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

Jeśli chcesz zabić (SIGKILL) procesy zamiast ich zakończenia (SIGTERM), jawnie wyślij sygnał SIGKILL, dodając --signal SIGKILLdo parametrów. Przykład crontab systemu:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND
t0r0X
źródło
-4

Dla httpd

ps eaxo pid, czas, komunikator | ogon -n + 2 | grep „httpd” | awk 'substr (0,9,1 $)> 0' | awk „{drukuj 1 $}”

czystej krwi
źródło