CPU/메모리 사용량이 너무 높아지면 Bash 스크립트가 자동으로 프로세스를 종료합니다.

CPU/메모리 사용량이 너무 높아지면 Bash 스크립트가 자동으로 프로세스를 종료합니다.

CPU 및/또는 메모리 사용량이 80%에 도달하면 프로세스를 종료하는 스크립트를 만들었습니다. 이런 일이 발생하면 종료된 프로세스 목록이 생성됩니다. 이를 개선하려면 어떻게 해야 합니까?

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

답변1

그래요추측하다해결하려는 문제는 때때로 문제가 발생하고 코어에 영구적으로 고정되어 있는 일부 프로세스가 상자에서 실행되고 있다는 것입니다.

가장 먼저 해야 할 일은 문제를 일으키는 프로그램을 복구하는 것입니다. 이것이 최고의 솔루션입니다. 나는 이것이 불가능하거나 문제가 해결될 때까지 상자를 계속 실행하기 위한 빠른 도구가 필요하다고 가정합니다.

적어도 관심 있는 하나의 프로그램만 실행하도록 스크립트를 제한하고 싶을 것입니다. 권한이 이와 같이 스크립트를 제한하는 것이 가장 좋습니다(예를 들어 스크립트가 사용자 X로 실행되고 X로 실행되는 유일한 다른 것은 프로그램입니다).

ulimit -t더 나은 방법은 프로그램이 사용할 수 있는 총 CPU 시간을 제한하는 것과 같은 것을 사용하는 것입니다 . 다시 말하지만, 모든 메모리를 소비하는 경우 커널이 이러한 제한을 적용하는지 확인하세요 . ulimit -v자세한 내용은 bash맨페이지(셸 내장)와 setrlimit(2)맨페이지를 참조하세요.

문제가 런어웨이 프로세스가 아니지만 너무 많은 프로세스가 실행 중인 경우에는 X 이상의 프로세스가 실행되지 않도록 어떤 형태의 잠금을 구현하십시오(또는 -- 익숙해 보일 것입니다 -- ulimit -u). 또한 이러한 프로세스의 스케줄러 우선 순위를 변경하거나( nice또는 사용) 정책을 로 변경하는 것을 renice더 근본적으로 고려할 수도 있습니다 .sched_setschedulerSCHED_IDLE

더 많은 제어가 필요하면 제어 그룹(cgroups)을 확인하세요. 실행 중인 커널에 따라 전체 프로세스 집합이 전체적으로 소비하는 CPU 시간, 메모리, I/O 등의 양을 실제로 제한할 수 있습니다. 컨트롤 그룹은 매우 유연하여 깨지기 쉬운 결함 없이 원하는 모든 작업을 수행할 수 있습니다. 아치 리눅스 위키에는cgroup 소개읽어볼 가치가 있는 이유는Neil Brown의 cgroups 시리즈LWN에서.

답변2

질문:

  • 숫자 필드를 정렬할 때 다음 옵션을 사용할 수 있습니다 -n. sort -nrk 2그렇지 않으면 값이 5.0인 행이 %CPU값이 12.0인 행보다 높아지게 됩니다.
  • 구현 에 따라 이 옵션을 사용하여 를 제거 ps할 수 있습니다 . 이렇게 하면 include 를 삭제하는 것을 방지할 수 있습니다 .--no-headersgrep -vPID
  • 내 생각엔 echo CPU USAGE is at $CPU_LOAD그게 당신의 뜻인 것 같아요 echo CPU USAGE is at $CPU_USAGE.
  • exit 0디버깅(?) 중에 삽입한 것을 제거하는 것을 잊었나 봅니다 .

스타일:

  • CPU_USAGE_THRESHOLD=800이 줄은 가장 유익한 내용이고 스크립트가 안정화된 후에도 변경될 수 있으므로 파일의 시작 부분으로 이동하는 것이 좋습니다 .
  • 옵션 을 반복하고 있습니다 -e: same as (as is ) ps -eo pid -eo pcpu -eo command.ps -eo pid -o pcpu -o commandps -eo pid,pcpu,command
  • 빈 조항이 있습니다 else. 이는 항상 처리되어야 하는 것처럼 보이지만 알 수 없는 이유로 처리되지는 않습니다.

답변3

스크립트를 작성했는데,프로세스 종료, CPU 사용량이 YY초 내에 XX%보다 크면 배열에 나열된 일부 프로세스가 종료되거나 ZZ초 이상 실행된 프로세스가 종료됩니다.

  • 파일 상단에 XX, YY, ZZ를 설정할 수 있습니다.
  • ps 또는 top을 사용하여 프로세스를 확인할 수 있습니다.
  • 확인할 수는 있지만 종료할 수는 없는 시험 실행 모드도 있습니다.
  • 마지막으로 일부 프로세스가 종료되면 스크립트는 이메일을 보냅니다.

노트:Github의 내 저장소는 다음과 같습니다.https://github.com/padosoft/kill-process

스크린샷은 다음과 같습니다.

         번호 1

인용하다

스크립트의 기본 부분(top 명령의 코드 요약):

#!/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
용법:
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]

답변4

대부분의 CPU/메모리를 사용하여 프로세스를 종료하면 문제가 발생합니다. 지금 컴퓨터에 무엇이 있는지 살펴보세요(여기서는 현재 firefox, systemd(init), Xorg, gnome-terminal, 커널 스레드 세트, xemacs; 중 하나) 그것들은 필수 불가결합니다.) 예를 들어 Linux의 OOM-killer를 조정하는 방법을 참조하세요.여기.

또한 "프로세스에서 사용하는 메모리"는 공유 라이브러리, 실행 파일, 심지어 부분 데이터 영역까지 있기 때문에 모호한 개념입니다. 각 사용자에게 사용된 공간의 작은 비율을 청구하여 몇 가지 수치를 계산할 수 있지만 이를 추가해도 실제로 "사용된 메모리"(또는 "프로세스가 종료되면 해제된" 메모리", 즉 공유 부분은 더 적게 제공되지 않습니다. 여전히 존재합니다) 뒷면).

관련 정보