Uccidi tutti i processi in esecuzione per più di 5 minuti da un determinato utente nello script bash di Linux


18

Ho bisogno del comando per uccidere i processi in esecuzione da almeno 5 minuti per un determinato processo.

Dovrò eseguire quel comando ogni cinque minuti circa.

Grazie mille !

(il sistema è Centos5)

linux  bash 

Risposte:


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

dove "procname" è un nome di processo e 300 è la soglia del tempo di esecuzione


Ottimo oneliner. L'ho usato senza -9essere un po 'più amichevole con i miei processi e ho aggiunto un grep -v defunct |precedente awkcome altrimenti, come potresti vedere procname <defunct>nel tuo output, il che renderebbe il comando awk non restituire un PID valido. E questo romperebbe il comando di uccisione.
Michael Härtl,

direi che $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')è un po 'più fluido, ma la risposta è comunque ottima
Yevgen

@WhiteHat come farebbe la stessa cosa ma per un processo con un certo pid?
Petar Vasilev,

una cosa ha sprecato il mio tempo è che: dovrebbe usare "con awk NOT"
cn123h,

6

Forse eseguire il comando long running in questo modo in un crontab?

timeout -k 300 command

5

La mia versione di kill script, sfruttando entrambe le risposte precedenti:

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

Filtra i processi in base a UID, NAME e se il tempo di esecuzione supera il limite: termina i processi e invia un rapporto via e-mail. Se non hai bisogno di quell'email, puoi semplicemente commentare l'ultima riga.


2

Ho trovato la soluzione in questa pagina: http://www.directadmin.com/forum/showthread.php?t=26179

Crea un file vuoto e chiamalo killlongproc.sh

Copia questo:

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

Smetti di farlo nel tuo cronjob

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

4
Di solito è una cattiva idea farlo. Quale problema stai davvero cercando di risolvere? Inoltre, non dovresti usarlo kill -9poiché non dà ai processi la possibilità di fare una pulizia graziosa prima di uscire.
In pausa fino a ulteriore avviso.

1
Ciò uccide i processi che hanno consumato una certa quantità di tempo della CPU (utente + sistema), non i processi che sono in esecuzione per una certa quantità di tempo reale (ad esempio, avviati prima di 1 ora).
Marki555,

2

C'è uno script qui che puoi modificare per fare quello che vuoi.

EDIT ha aggiunto lo script di seguito

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

Non ho abbastanza conoscenze per modificarlo, ecco perché te lo chiedo

2
Troppo complicato. È possibile utilizzare la colonna etimesdi psper mostrare direttamente i secondi trascorsi dall'inizio del processo (non è necessario calcolarlo dall'inizio).
Marki555,

@ Marki555 sì, questo è vero. Tuttavia, su sistemi con versioni psche non supportano etimes(solo etime) questa è un'ottima alternativa. L'ho usato solo quando la risposta migliore mi ha dato un errore daps
Mike,

0

Ho dovuto risolvere un compito simile e non ha bisogno di una sceneggiatura. Per terminare i processi (signal SIGTERM) dell'eseguibile "THECOMMAND":

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

La limitazione per l'utente corrente -u $USERè necessaria solo per evitare messaggi di errore non necessari se anche altri utenti eseguono "THECOMMAND". Nel tuo crontab utente inseriresti quanto segue:

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

In un crontab di sistema (utente 'root') dovresti aggiungere quanto segue:

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

Se si desidera eliminare (SIGKILL) i processi anziché terminarli (SIGTERM), inviare esplicitamente il segnale SIGKILL aggiungendo --signal SIGKILLai parametri. Esempio per un crontab di sistema:

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

-4

Per httpd

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.