Bash 脚本检查特定进程的 CPU 使用率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14885598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:34:33  来源:igfitidea点击:

Bash script checking cpu usage of specific process

bashintegerarithmetic-expressions

提问by user2073780

First off, I'm new to this. I have some experience with windows scripting and apple script but not much with bash. What I'm trying to do is grab the PID and %CPU of a specific process. then compare the %CPU against a set number, and if it's higher, kill the process. I feel like I'm close, but now I'm getting the following error:

首先,我是新手。我对 Windows 脚本和 Apple 脚本有一些经验,但对 bash 没有多少经验。我想要做的是获取特定进程的 PID 和 %CPU。然后将 %CPU 与一组数字进行比较,如果它更高,则终止该进程。我觉得我很接近,但现在我收到以下错误:

[[: 0.0: syntax error: invalid arithmetic operator (error token is ".0")

[[: 0.0: 语法错误:算术运算符无效(错误标记为“.0”)

what am I doing wrong? here's my code so far:

我究竟做错了什么?到目前为止,这是我的代码:

#!/bin/bash
declare -i app_pid
declare -i app_cpu
declare -i cpu_limit
app_name="top"
cpu_limit="50"
app_pid=`ps aux | grep $app_name | grep -v grep | awk {'print '}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print '}`
if [[ ! $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

Obviously I'm going to replace the echos in the if/then statement but it's acting as if the statement is true regardless of what the cpu load actually is (I tested this by changing the -gt to -lt and it still echoed "crap"

显然,我将替换 if/then 语句中的回声,但无论 cpu 负载实际是多少,它都表现得好像该语句是真的(我通过将 -gt 更改为 -lt 进行了测试,但它仍然回显“废话” ”

Thank you for all the help. Oh, and this is on a OS X 10.7 if that is important.

谢谢大家的帮助。哦,如果这很重要,这是在 OS X 10.7 上。

回答by that other guy

The problem is that bash can't handle decimals. You can just multiply them by 100 and work with plain integers instead:

问题是 bash 不能处理小数。您可以将它们乘以 100 并使用普通整数代替:

#!/bin/bash
declare -i app_pid
declare -i app_cpu
declare -i cpu_limit
app_name="top"
cpu_limit="5000"
app_pid=`ps aux | grep $app_name | grep -v grep | awk {'print '}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print *100'}`
if [[ $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

Keep in mind that CPU percentage is a suboptimal measurement of application health. If you have two processes running infinite loops on a single core system, no other application of the same priority will ever go over 33%, even if they're trashing around.

请记住,CPU 百分比是应用程序运行状况的次优度量。如果您有两个进程在单核系统上无限循环运行,那么没有其他具有相同优先级的应用程序会超过 33%,即使它们正在乱扔垃圾。

回答by Anton Kovalenko

I recommend taking a look at the facilities of psto avoid multiple horrible things you do.

我建议看一下 的设施,ps以避免你做的多件可怕的事情。

On my system (psfrom procps on linux, GNU awk) I would do this:

在我的系统上(ps来自 linux 上的 procps,GNU awk)我会这样做:

ps -C "$app-name" -o pid=,pcpu= | 
    awk --assign maxcpu="$cpu_limit" '>maxcpu {print "crappy pid",}'

回答by Hasan

#!/bin/sh
PROCESS="java"
PID=`pgrep $PROCESS | tail -n 1`
CPU=`top -b -p $PID -n 1 | tail -n 1 | awk '{print }'`
echo $CPU

回答by redolent

I use topto check some details. It provides a little more details like cpu time.

top用来检查一些细节。它提供了更多详细信息,例如 CPU 时间。

top -l 1  | grep $app_name

回答by Erik Lundmark

I came up with this, using top and bc.

我想出了这个,使用 top 和 bc。

Use it by passing in ex: ./script apache2 50 # max 50%

通过传入 ex 来使用它: ./script apache2 50 # max 50%

If there are many PIDs matching your program argument, only one will be calculated, based on how top lists them. I could have extended the script by catching them all and avergaing the percentage or something, but this will have to do.

如果有许多 PID 与您的程序参数匹配,则将根据 top 列出它们的方式只计算一个。我可以通过捕获它们并平均百分比或其他东西来扩展脚本,但这必须这样做。

You can also pass in a number, ./script.sh 12345 50, which will force it to use an exact PID.

您还可以传入一个数字, ./script.sh 12345 50,这将强制它使用精确的 PID。

#!/bin/bash

# 1: ['command\ name' or PID number(,s)] 2: MAX_CPU_PERCENT

[[ $# -ne 2 ]] && exit 1
PID_NAMES=
# get all PIDS as nn,nn,nn
if [[ ! "$PID_NAMES" =~ ^[0-9,]+$ ]] ; then
    PIDS=$(pgrep -d ',' -x $PID_NAMES)
else
    PIDS=$PID_NAMES
fi
#  echo "$PIDS $MAX_CPU"
MAX_CPU=""
MAX_CPU="$(echo "($MAX_CPU+0.5)/1" | bc)"
LOOP=1
while [[ $LOOP -eq 1 ]] ; do
    sleep 0.3s
    # Depending on your 'top' version and OS you might have
    #   to change head and tail line-numbers
    LINE="$(top -b -d 0 -n 1 -p $PIDS | head -n 8 \
        | tail -n 1 | sed -r 's/[ ]+/,/g' | \
        sed -r 's/^\,|\,$//')"
    # If multiple processes in $PIDS, $LINE will only match\
    #   the most active process
    CURR_PID=$(echo "$LINE" | cut -d ',' -f 1)
    # calculate cpu limits
    CURR_CPU_FLOAT=$(echo "$LINE"| cut -d ',' -f 9)
    CURR_CPU=$(echo "($CURR_CPU_FLOAT+0.5)/1" | bc)
    echo "PID $CURR_PID: $CURR_CPU""%"
    if [[ $CURR_CPU -ge $MAX_CPU ]] ; then
        echo "PID $CURR_PID ($PID_NAMES) went over $MAX_CPU""%"
        echo "[[ $CURR_CPU""% -ge $MAX_CPU""% ]]"
        LOOP=0
        break
    fi
done
echo "Stopped"

回答by Xoroz

Erik, I used a modified version of your code to create a new script that does something similar. Hope you don't mind it.

Erik,我使用了您代码的修改版本来创建一个执行类似操作的新脚本。希望你不要介意。

A bash script to get the CPU usage by process usage:

根据进程使用情况获取 CPU 使用率的 bash 脚本:

nohup ./check_proc bwengine 70 &

bwegnineis the process name we want to monitor 70 is to log only when the process is using over 70% of the CPU.

bwegnine是我们要监控的进程名称 70 是仅当进程使用超过 70% 的 CPU 时才记录日志。

Check the logs at: /var/log/check_procs.log

检查日志: /var/log/check_procs.log

The output should be like:

输出应该是这样的:

DATE | TOTAL CPU | CPU USAGE | Process details

Example:

例子:

03/12/14 17:11 |20.99|98| ProdPROXY-ProdProxyPA.tra

03/12/14 17:11 |20.99|100| ProdPROXY-ProdProxyPA.tra

Link to the full blog: http://felipeferreira.net/?p=1453

完整博客的链接:http: //felipeferreira.net/?p=1453

回答by David C. Rankin

It is also useful to have app_userinformation available to test whether the current user has the rights to kill/modify the running process. This information can be obtained along with the needed app_pidand app_cpuby using readeliminating the need for awkor any other 3rd party parser:

拥有app_user可用于测试当前用户是否有权终止/修改正在运行的进程的信息也很有用。此信息可以与所需的信息一起获得,app_pidapp_cpu通过使用read消除对awk任何其他第 3 方解析器的需要:

read app_user app_pid tmp_cpu stuff <<< \
$( ps aux | grep "$app_name" | grep -v "grep\|defunct\|${0##*/}" )

You can then get your app_cpu * 100with:

然后你可以得到你app_cpu * 100的:

app_cpu=$((${tmp_cpu%.*} * 100))

Note:Including defunctand ${0##*/}in grep -vprevents against multiple processes matching $app_name.

注意:包括defunct${0##*/}ingrep -v防止多个进程匹配$app_name.