Giết tất cả các quy trình đang chạy trong hơn 5 phút bởi một người dùng nhất định trong tập lệnh bash linux


18

Tôi cần lệnh để tiêu diệt các tiến trình đã chạy từ ít nhất 5 phút cho một quy trình nhất định.

Tôi sẽ phải chạy lệnh đó cứ sau năm phút.

Cảm ơn rất nhiều !

(hệ thống là Centos5)

linux  bash 

Câu trả lời:


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

trong đó "Procname" là tên quy trình và 300 đang chạy ngưỡng thời gian


Tuyệt vời oneliner. Tôi đã sử dụng nó mà không -9phải là một chút thân thiện hơn với các quy trình của tôi và đã thêm grep -v defunct |trước đó awknhư những gì bạn có thể thấy procname <defunct>trong đầu ra của mình, điều này sẽ khiến lệnh awk không trả về một PID hợp lệ. Và điều này sẽ phá vỡ lệnh kill.
Michael Härtl

Tôi sẽ nói $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')là một chút mịn màng hơn nhưng dù sao câu trả lời là tuyệt vời
Yevgen

@WhiteHat làm thế nào để làm điều tương tự nhưng đối với một quá trình với pid nhất định?
Petar Vasilev

một điều lãng phí thời gian của tôi là: nên sử dụng 'với awk KHÔNG "
cn123h

6

Có thể chạy lệnh chạy dài như thế này trong một crontab?

timeout -k 300 command

5

Phiên bản kill script của tôi, nhận lợi ích từ cả hai câu trả lời trước:

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

Nó lọc quy trình theo UID, NAME và nếu thời gian thực hiện vượt quá giới hạn - giết chết các quy trình và gửi báo cáo đến email. Nếu bạn không cần email đó - bạn chỉ có thể nhận xét dòng cuối cùng.


2

Tôi đã tìm thấy giải pháp trên trang này: http://www.directadmin.com/forum/showthread.php?t=26179

Tạo một tập tin trống và gọi nó là killlongproc.sh

Sao chép cái này:

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

Dừng lại trong cronjob của bạn

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

4
Nó thường là một ý tưởng tồi để làm điều này. Vấn đề gì bạn đang thực sự cố gắng giải quyết? Ngoài ra, bạn không nên sử dụng kill -9vì nó không tạo cơ hội để dọn dẹp duyên dáng trước khi thoát.
Tạm dừng cho đến khi có thông báo mới.

1
Điều này giết chết các quy trình tiêu tốn một lượng thời gian CPU (người dùng + hệ thống), chứ không phải các quy trình đang chạy trong một khoảng thời gian thực (ví dụ: bắt đầu trước 1 giờ).
Marki555

2

Có một kịch bản ở đây mà bạn có thể sửa đổi để làm những gì bạn muốn.

EDIT đã thêm đoạn script bên dưới

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

Tôi không có đủ kiến ​​thức để sửa đổi nó, đó là lý do tại sao tôi hỏi bạn

2
Quá phức tạp. Bạn có thể sử dụng cột etimescủa psđể hiển thị trực tiếp các giây đã trôi qua kể từ khi bắt đầu quá trình (không cần tính toán từ thời gian bắt đầu).
Marki555

@ Marki555 có, điều này là đúng. Tuy nhiên, trên các hệ thống có phiên bản pskhông hỗ trợ etimes(chỉ etime) thì đây là một sự thay thế tuyệt vời. Tôi chỉ sử dụng nó khi câu trả lời hàng đầu cho tôi một lỗi từps
mike

0

Tôi đã phải giải quyết một nhiệm vụ tương tự, và nó không cần một kịch bản. Để kết thúc quá trình (tín hiệu SIGTERM) của "THECOMMAND" thực thi:

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

Hạn chế đối với người dùng hiện tại -u $USERchỉ cần thiết để tránh các thông báo lỗi không cần thiết nếu người dùng khác cũng chạy "THECOMMAND". Trong crontab người dùng của riêng bạn, bạn sẽ nhập như sau:

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

Trong một crontab hệ thống (người dùng 'root'), bạn sẽ thêm vào như sau:

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

Nếu bạn muốn tiêu diệt (SIGKILL) các quy trình thay vì chấm dứt (SIGTERM) chúng, hãy gửi rõ ràng tín hiệu SIGKILL bằng cách thêm --signal SIGKILLvào các tham số. Ví dụ cho một crontab hệ thống:

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

-4

Dành cho httpd

ps eaxo pid, thời gian, comm | đuôi -n + 2 | grep 'httpd' | awk 'đế ($ 0,9,1)> 0' | awk '{in $ 1}'

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.