我制作了一个小脚本来杀死PID,如果它们超过了预期的CPU使用率。它有效,但有一个小问题。
脚本:
while [ 1 ];
do
cpuUse=$(ps -eo %cpu | sort -nr | head -1)
cpuMax=80
PID=$(ps -eo %cpu,pid | sort -nr | head -1 | cut -c 6-20)
if [ $cpuUse -gt $cpuMax ] ; then
kill -9 "$PID"
echo Killed PID $PID at the usage of $cpuUse out of $cpuMax
fi
exit 0
sleep 1;
done
如果整数长度为三位数,则可以正常工作;如果整数减少到两位则失败并显示:
./ kill.sh:line 7:[:51.3:预期的整数表达式
我的问题是,如何让bash理解分隔符,以便它可以杀死三位数的进程。
答案 0 :(得分:1)
您可能正在获得该变量的领先空间。尝试使用tr来首先剥离所有空格:
cpuUse=$(ps -eo %cpu | sort -nr | head -1 | tr -d '[[:space:]]')
从cpuUse
变量点后删除文字
cpuUse="${cpuUse%%.*}"
最好在if条件中使用引号:
if [ "$cpuUse" -gt "$cpuMax" ] ; then
或者更好地使用算术运算符(( and ))
:
if (( cpuUse > cpuMax )); then
答案 1 :(得分:1)
如您所见,bash不会记录非整数。在进行比较之前,您需要从$cpuUse
中删除小数点和以下数字“:
cpuUse=$(sed 's/\..*/' <<<$cpuUse)
然而,这确实是awk
的工作。它将简化你正在做的很多事情。每当您发现greps
greps
,head
,然后cuts
时,您应该处理awk。 Awk可以轻松地将这些多个管道seds,greps,cut,heads组合成一个命令。
顺便说一下,正确的 ps
命令是:
$ ps -eocpu="",pid=""
使用=""
将消除标题并简单地为您提供CPU和PID。
查看您的程序,没有必要进行排序。您只是在寻找高于$cpuMax
阈值的所有流程:
ps -eo %cpu="",pid="" | awk '$1 > 80 {print $2}'
打印出超过阈值的PID。 Awk
会自动循环遍历整个输入。 Awk还会自动将每一行划分为多个列,并为每个行分配一个$1
及更高的变量。您可以使用-F
参数更改字段分隔符。
以上awk
表示查找第一列高于80%的所有行(CPU使用率)并打印出第二列(pid)。
如果您想要一些灵活性并且能够传递不同的$cpuMax
,您可以使用-v
参数来设置Awk变量:
ps -eo %cpu="",pid="" | awk -vcpuMax=$cpuMax '$1 > cpuMax {print $2}'
现在您可以将此命令的输出括起来删除所有这些进程:
pid=$(ps -eo %cpu="",pid="" | awk -vcpuMax=$cpuMax '$1 > cpuMax {print $2}')
if [[ -n $pid ]]
then
kill -9 $pid
echo "Killed the following processes:" $pid
fi