Убийте всі процеси, які певний користувач працює понад 5 хвилин у скрипті lhus bash


18

Мені потрібна команда, щоб знищити процеси, які працюють протягом принаймні 5 хвилин для певного процесу.

Мені доведеться виконувати цю команду кожні п’ять хвилин.

Завдяки мільйонів !

(система Centos5)

linux  bash 

Відповіді:


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.
Michael Härtl

я б сказав $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}'), трохи легше, але відповідь все одно чудова
Євген

@WhiteHat як би зробити те ж саме, але для процесу з певним pid?
Петро Василев

одне, що я витратив моє час, це те, що: слід використовувати "з awk НЕ"
cn123h

6

Може, запустити таку довгу команду, що працює, як у crontab?

timeout -k 300 command

5

Моя версія сценарію kill, використовуючи обидві попередні відповіді:

#!/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, і якщо час виконання перевищує ліміт - вбиває процеси та надсилає звіт на електронну пошту. Якщо вам не потрібен цей електронний лист - ви можете просто прокоментувати останній рядок.


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

Існує скрипт тут , що ви могли б змінити , щоб зробити те , що ви хочете.

EDIT додав сценарій нижче

#!/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". У вашому власному кроні користувача ви введете наступне:

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

У системний crontab (користувальницький корінь) ви додасте наступне:

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

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.