预期的整数表达式[bash不明白。]

时间:2014-02-02 16:07:35

标签: bash integer cpu-usage

我制作了一个小脚本来杀死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理解分隔符,以便它可以杀死三位数的进程。

2 个答案:

答案 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 grepshead,然后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