Tập lệnh Bash tự động giết các tiến trình khi mức sử dụng CPU / bộ nhớ quá cao


11

Tôi đã tạo một tập lệnh giết chết các tiến trình nếu việc sử dụng CPU và / hoặc bộ nhớ đạt 80%. Nó tạo ra một danh sách các quá trình bị giết khi điều này xảy ra. Tôi có thể làm gì để cải thiện nó?

while [ 1 ];
do 
echo
echo checking for run-away process ...

CPU_USAGE=$(uptime | cut -d"," -f4 | cut -d":" -f2 | cut -d" " -f2 | sed -e "s/\.//g")
CPU_USAGE_THRESHOLD=800
PROCESS=$(ps aux r)
TOPPROCESS=$(ps -eo pid -eo pcpu -eo command | sort -k 2 -r | grep -v PID | head -n 1)

if [ $CPU_USAGE -gt $CPU_USAGE_THRESHOLD] ; then
  kill -9 $(ps -eo pid | sort -k 1 -r | grep -v PID | head -n 1) #original
  kill -9 $(ps -eo pcpu | sort -k 1 -r | grep -v %CPU | head -n 1)
  kill -9 $TOPPROCESS
  echo system overloading!
  echo Top-most process killed $TOPPROCESS
      echo CPU USAGE is at $CPU_LOAD

else
    fi
    exit 0
    sleep 1;
    done

3
Bạn đã thử chạy kịch bản chưa? while [ 1 ]làm cho tôi tự hỏi bao nhiêu CPU kịch bản này sẽ tiêu thụ. Ngoài ra, 3 cuộc gọi đến kill -9trong một kịch bản chạy liên tục? Điều này mang lại cho tôi cảm giác ớn lạnh ...
rahmu

1
Dù sao thì avatar đẹp, @rahmu anh ấy có một sleep 1vòng lặp
daisy

1
Thứ hai đầu tiên của tháng và PC của tôi đang kiểm tra bộ RAID6 (chậm). Tải CPU dễ dàng đạt đỉnh trên 8 vì nó liên tục chờ đĩa IO từ bộ RAID này. Không có gì sai, hệ thống vẫn rất nhạy. Kịch bản của bạn sẽ giết firefox của tôi, chỉ sử dụng 3,6% trong số 400% có sẵn. Chỉ cần nói rằng bạn có thể đang săn ma với kịch bản này. BTW: hệ thống của bạn sẽ không bị hỏng do tải cao và khi hết bộ nhớ, kernel sẽ thực hiện phỏng đoán bán giáo dục về quá trình nào sẽ giết.
jippie

Sau đó, giết quá trình dựa trên tải sẽ ổn hay không ????
Ketan Patel

Trong trường hợp sử dụng của tôi, việc giết chóc là không mong muốn.
jippie

Câu trả lời:


11

Tôi đoán vấn đề bạn muốn giải quyết là bạn có một số quy trình đang chạy trên hộp của bạn mà đôi khi hoạt động sai, và ngồi mãi mãi chốt một lõi.

Điều đầu tiên bạn muốn làm là cố gắng sửa chương trình phát điên. Đó là giải pháp tốt nhất. Tôi sẽ giả định rằng điều đó là không thể, hoặc bạn cần một cái kluge nhanh để giữ cho hộp của bạn chạy cho đến khi nó được cố định.

Bạn, tối thiểu, muốn giới hạn tập lệnh của bạn chỉ nhấn vào một chương trình bạn quan tâm. Sẽ tốt nhất nếu quyền hạn chế tập lệnh của bạn như thế này (ví dụ: tập lệnh của bạn chạy với tư cách người dùng X, điều duy nhất khác chạy dưới dạng X là chương trình).

Thậm chí tốt hơn là sử dụng một cái gì đó như ulimit -tđể giới hạn tổng thời gian CPU mà chương trình có thể sử dụng. Tương tự, nếu nó tiêu thụ hết bộ nhớ, hãy kiểm tra ulimit -v. Hạt nhân thi hành các giới hạn này; xem bashtrang hướng dẫn (đây là phần tích hợp sẵn) và setrlimit(2)trang này để biết chi tiết.

Nếu vấn đề không phải là một quá trình chạy amok, mà thay vào đó chỉ là quá nhiều quá trình đang chạy, thì hãy thực hiện một số hình thức khóa để ngăn không cho X chạy (hoặc điều này sẽ trở nên quen thuộc ulimit -u). Bạn cũng có thể xem xét thay đổi mức độ ưu tiên của trình lập lịch biểu của các quy trình đó (sử dụng nicehoặc renice) hoặc thậm chí quyết liệt hơn, sử dụng sched_setschedulerđể thay đổi chính sách thành SCHED_IDLE.

Nếu bạn cần kiểm soát nhiều hơn, hãy xem một nhóm kiểm soát (cgroups). Tùy thuộc vào nhân bạn đang chạy, bạn thực sự có thể giới hạn thời gian CPU, bộ nhớ, I / O, v.v ... mà cả một nhóm các quy trình cùng nhau tiêu thụ. Các nhóm kiểm soát khá linh hoạt; họ có thể làm bất cứ điều gì bạn đang cố gắng làm, mà không cần bất kỳ klug mỏng manh nào. Arch Linux Wiki có phần giới thiệu về các nhóm đáng đọc, cũng như loạt cgroups của Neil Brown tại LWN.


3

Các vấn đề:

  • Khi sắp xếp các trường số có thể bạn muốn sử dụng -ntùy chọn : sort -nrk 2. Nếu không, một dòng có %CPUgiá trị 5.0 sẽ kết thúc cao hơn một dòng có giá trị 12.0.
  • Tùy thuộc vào psviệc triển khai của bạn, bạn có thể muốn sử dụng --no-headerstùy chọn để thoát khỏi grep -v. Điều đó ngăn bạn loại bỏ các lệnh có chứa PID.
  • Tôi đoán thay vì echo CPU USAGE is at $CPU_LOAD, bạn có nghĩa là echo CPU USAGE is at $CPU_USAGE.
  • Tôi đoán bạn đã quên xóa cái exit 0mà bạn đã chèn trong quá trình gỡ lỗi (?).

Phong cách:

  • Bạn có thể muốn di chuyển CPU_USAGE_THRESHOLD=800dòng đến đầu tập tin, vì đây là điều có nhiều thông tin nhất và rất có thể sẽ bị thay đổi ngay cả khi tập lệnh của bạn ổn định.
  • Bạn đang lặp lại -etùy chọn: ps -eo pid -eo pcpu -eo commandgiống như ps -eo pid -o pcpu -o command(như vậy ps -eo pid,pcpu,command).
  • Có một elseđiều khoản trống . Điều đó luôn có vẻ như cần được xử lý, nhưng không phải vì một lý do nào đó.

2

Việc tắt các tiến trình đang sử dụng hầu hết CPU / bộ nhớ đang gặp rắc rối: Chỉ cần xem những gì chúng hiện đang có trên máy của bạn (hiện tại là firefox, systemd (init), Xorg, gnome-terminal, một tập hợp các luồng nhân, xemacs; không ai trong số đó là phân phát). Xem cách điều chỉnh OOM-killer của Linux, ví dụ ở đây .

Cũng lưu ý rằng "bộ nhớ được sử dụng bởi quy trình" là một khái niệm mơ hồ, vì có các thư viện dùng chung, các tệp thực thi được chia sẻ và thậm chí là một phần của các vùng dữ liệu. Người ta có thể đưa ra một số con số bằng cách sạc cho mỗi người dùng một phần dung lượng đã sử dụng, nhưng thậm chí thêm vào đó thực sự không mang lại "bộ nhớ đã sử dụng" (thậm chí còn ít hơn "giải phóng bộ nhớ nếu quá trình biến mất", các phần được chia sẻ ở lại phía sau).


1

Tôi đã tạo một tập lệnh, quy trình tiêu diệt , giết chết một số quy trình được liệt kê trong một mảng, nếu mức sử dụng CPU lớn hơn XX% trong vài giây YY hoặc giết các quy trình chạy nhiều hơn ZZ giây.

  • Bạn có thể đặt XX, YY, ZZ ở đầu tệp.
  • Bạn có thể sử dụng ps hoặc top cho quá trình kiểm tra.
  • Có một chế độ chạy khô quá, để kiểm tra nhưng không giết.
  • Cuối cùng, tập lệnh sẽ gửi email nếu một số quy trình bị giết.

LƯU Ý: Đây là repo của tôi trên Github: https://github.com/padosoft/kill- process

Đây là một ảnh chụp màn hình:

         ss # 1

Người giới thiệu

Phần thiết yếu của tập lệnh (tóm tắt mã cho lệnh trên):

#!/usr/bin/env bash

#max cpu % load
MAX_CPU=90
#max execution time for CPU percentage > MAX_CPU (in seconds 7200s=2h)
MAX_SEC=1800
#sort by cpu
SORTBY=9

#define a processes command name to check
declare -a KILLLIST
KILLLIST=("/usr/sbin/apache2" "/usr/bin/php5-cgi")

#iterate for each process to check in list
for PROCESS_TOCHECK in ${KILLLIST[*]}
do

    #retrive pid with top command order by SORTBY
    PID=$(top -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $1}')

    CPU=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $9}')
    TIME_STR=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $11}')

    # Decode the top CPU time format [dd-]hh:mm.ss.
    TIME_SEC=0
    IFS="-:" read c1 c2 c3 c4 <<< "$TIME_STR"

    #with top command time format is hh:mm.ss, so truncare seconds in c2
    c2=${c2%%.*}

    if [ -n "$c4" ]
    then
      TIME_SEC=$((10#$c4+60*(10#$c3+60*(10#$c2+24*10#$c1))))
    elif [ -n "$c3" ]
    then
      if [ "$CMD" = "ps" ]; then
        TIME_SEC=$((10#$c3+60*(10#$c2+60*10#$c1)))
      else
        TIME_SEC=$(((10#$c3*24)*60*60)+60*(10#$c2+60*10#$c1))             
      fi   
    else
      if [ "$CMD" = "ps" ]; then
        TIME_SEC=$((10#0+(10#$c2+60*10#$c1)))
      else
        TIME_SEC=$((10#0+60*(10#$c2+60*10#$c1)))
      fi
    fi

    #check if need to kill process
    if [ $CPU -gt $MAX_CPU ] && [ $TIME_SEC -gt $MAX_SEC ]; then
        kill -15 $PID
    fi

done
Sử dụng:
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]

Có vẻ sortnên sort -k9nr. Nếu không n, sẽ nhận được `5,9`> 29.4.
lk_vc
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.