Убить все процессы, которые выполняются более 5 минут данным пользователем в сценарии bash linux

18

Мне нужна команда, чтобы убить процессы, которые были запущены по крайней мере 5 минут для данного процесса.

Мне придется выполнять эту команду каждые пять минут или около того.

Бесконечно благодарен !

(система Centos5)


источник

Ответы:

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

где «procname» - это имя процесса, а 300 - порог времени выполнения

Белая шляпа
источник
Отличный лайнер. Я использовал его, не -9будучи немного более дружественным к своим процессам, и добавил grep -v defunct |ранее, awkкак и другое, что вы можете увидеть procname <defunct>в своем выводе, что заставит команду awk не возвращать действительный PID. И это сломало бы команду kill.
Михаэль Хертл
я бы сказал, $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')что это немного более плавно, но в любом случае ответ будет отличным
Евгений
@WhiteHat, как сделать то же самое, но для процесса с определенным pid?
Петр Васильев
одна вещь, потраченная впустую мое время, состоит в том, что: следует использовать 'с awk NOT'
cn123h
6

Может, запустите такую ​​длительную команду в crontab?

timeout -k 300 command
АТХ
источник
5

Моя версия сценария уничтожения, использующая преимущества обоих предыдущих ответов:

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

Он фильтрует процесс по UID, NAME и, если время выполнения превышает лимит, убивает процессы и отправляет отчет на электронную почту. Если вам не нужно это письмо - вы можете просто прокомментировать последнюю строку.

Viperet
источник
2

Я нашел решение на этой странице: http://www.directadmin.com/forum/showthread.php?t=26179

Сделайте пустой файл и назовите его killlongproc.sh

Скопируйте это:

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

Останови это в своем хрене

15 * * * * * root /{directory}/./killongproc.sh
Приостановлено до дальнейшего уведомления.
источник
4
Обычно это плохая идея. Какую проблему вы действительно пытаетесь решить? Кроме того, вы не должны использовать kill -9его, так как он не дает процессам возможности выполнить аккуратную очистку перед выходом.
Приостановлено до дальнейшего уведомления.
1
Это убивает процессы, которые занимают некоторое количество процессорного времени (пользователь + система), а не процессы, которые выполняются в течение некоторого времени в реальном времени (например, запущенные до 1 часа).
Marki555
2

Существует скрипт здесь , что вы могли бы изменить , чтобы сделать то , что вы хотите.

РЕДАКТИРОВАТЬ добавил скрипт ниже

#!/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
Время пришло
источник
У меня нет достаточно знаний, чтобы изменить его, поэтому я прошу вас
2
Слишком сложно. Вы можете использовать столбец etimesиз , psчтобы показать вам непосредственно в истекших секунды с момента начала процесса (нет необходимости вычислять его от времени начала).
Marki555
@ Marki555 да, это правда. Однако в системах с версиями, psкоторые не поддерживают etimes(только etime), это отличная альтернатива. Я только использовал это, когда главный ответ дал мне ошибку отps
Майк
0

Мне пришлось решить аналогичную задачу, и для этого не нужен сценарий. Для завершающих (сигнальных SIGTERM) процессов исполняемого файла "THECOMMAND":

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

Ограничение для текущего пользователя -u $USER необходимо только во избежание ненужных сообщений об ошибках, если другие пользователи также запускают «THECOMMAND». В вашем собственном пользовательском crontab вы должны ввести следующее:

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

В системном crontab (пользователь 'root') вы добавили бы следующее:

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

Если вы хотите уничтожить (SIGKILL) процессы вместо их завершения (SIGTERM), явным образом отправьте сигнал SIGKILL, добавив --signal SIGKILLк параметрам. Пример для системного crontab:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND
t0r0X
источник
-4

Для httpd

ps eaxo pid, время, комм | хвост -n + 2 | grep 'httpd' | awk 'substr ($ 0,9,1)> 0' | awk '{print $ 1}'

puremind
источник