Mate todos os processos em execução por mais de 5 minutos por um determinado usuário no script linux bash


18

Eu preciso do comando para matar processos em execução desde pelo menos 5 minutos para um determinado processo.

Vou ter que executar esse comando a cada cinco minutos ou mais.

Graças um milhão!

(o sistema é Centos5)

linux  bash 

Respostas:


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

onde "procname" é um nome de processo e 300 está no limite de tempo de execução


Ótimo oneliner. Eu o usei sem -9ser um pouco mais amigável com meus processos e adicionei um grep -v defunct |antes awkcomo de outra maneira, como você pode ver procname <defunct>em sua saída, o que faria o comando awk não retornar um PID válido. E isso quebraria o comando de matar.
Michael Härtl

eu diria que $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')é um pouco mais suave pouco, mas a resposta é grande de qualquer maneira
Yevgen

@WhiteHat, como faria a mesma coisa, exceto por um processo com certo pid?
Petar Vasilev

uma coisa que desperdicei meu tempo é que: deveria usar 'com awk NOT "
cn123h 28/02/19

6

Talvez execute o comando de longa execução como este em um crontab?

timeout -k 300 command

5

Minha versão do script kill, aproveitando as duas respostas anteriores:

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

Ele filtra o processo por UID, NAME e se o tempo de execução exceder o limite - mata os processos e envia o relatório para o email. Se você não precisar desse email, basta comentar a última linha.


2

Encontrei a solução nesta página: http://www.directadmin.com/forum/showthread.php?t=26179

Crie um arquivo vazio e chame-o de killlongproc.sh

Copie isto:

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

Pare com isso no seu cronjob

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

4
Geralmente é uma má idéia fazer isso. Que problema você realmente está tentando resolver? Além disso, você não deve usá- kill -9lo, pois isso não dá aos processos a chance de fazer uma limpeza normal antes de sair.
Pausado até novo aviso.

1
Isso mata processos que consumiram uma certa quantidade de tempo da CPU (usuário + sistema), não processos que estão sendo executados por uma quantidade de tempo real (por exemplo, iniciados antes de 1 hora).
precisa saber é o seguinte

2

Há um script aqui que você pode modificar para fazer o que deseja.

EDIT adicionou o script abaixo

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

Não tenho conhecimento enought para modificá-lo, é por isso que eu estou pedindo para você

2
Muito complicado. Você pode usar a coluna etimesde pspara mostrar diretamente os segundos decorridos desde o início do processo (não é necessário calculá-lo desde o início).
precisa saber é o seguinte

@ Marki555 sim, isso é verdade. No entanto, em sistemas com versões psque não suportam etimes(apenas etime), essa é uma ótima alternativa. Eu apenas o usei quando a resposta principal me deu um erro de #ps
mike

0

Eu tive que resolver uma tarefa semelhante, e ela não precisa de um script. Para encerrar (sinalizar SIGTERM) os processos do executável "THECOMMAND":

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

A restrição ao usuário atual -u $USERé necessária apenas para evitar mensagens de erro desnecessárias se outros usuários também executarem "THECOMMAND". No seu próprio usuário crontab, você digitaria o seguinte:

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

Em um sistema crontab (usuário 'root'), você adicionaria o seguinte:

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

Se você deseja matar (SIGKILL) os processos em vez de finalizá-los (SIGTERM), envie explicitamente o sinal SIGKILL adicionando --signal SIGKILLaos parâmetros. Exemplo para um sistema crontab:

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

-4

Para httpd

ps eaxo pid, tempo, comunicação | cauda -n + 2 | grep 'httpd' | awk 'substr ($ 0,9,1)> 0' | awk '{print $ 1}'

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.