6

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

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

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

#!/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 $2'}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print $3'}`
if [[ ! $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

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

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

4

7 回答 7

11

我建议您查看 的设施,ps以避免您做多种可怕的事情。

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

ps -C "$app-name" -o pid=,pcpu= | 
    awk --assign maxcpu="$cpu_limit" '$2>maxcpu {print "crappy pid",$1}'
于 2013-02-14T23:08:14.960 回答
9

问题是 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 $2'}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print $3*100'}`
if [[ $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

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

于 2013-02-14T23:00:26.060 回答
3
#!/bin/sh
PROCESS="java"
PID=`pgrep $PROCESS | tail -n 1`
CPU=`top -b -p $PID -n 1 | tail -n 1 | awk '{print $9}'`
echo $CPU
于 2015-02-28T07:56:10.327 回答
0

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

在 Linux 上,这将是:

top -b -n 1  | grep $app_name

在 Mac 上,使用其 BSD 版本的 top:

top -l 1  | grep $app_name
于 2013-12-02T22:32:23.393 回答
0

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

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

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

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

#!/bin/bash

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

[[ $# -ne 2 ]] && exit 1
PID_NAMES=$1
# 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="$2"
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"
于 2014-01-27T13:30:01.973 回答
0

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

一个 bash 脚本,用于按进程使用情况获取 CPU 使用情况:

nohup ./check_proc bwengine 70 &

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

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

输出应该是这样的:

DATE | TOTAL CPU | CPU USAGE | Process details

例子:

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

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

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

于 2014-03-12T20:20:58.717 回答
0

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

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

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

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

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

于 2014-08-29T02:03:05.130 回答