0

我正在将顶部命令输出写入文本文件。我正在尝试编写一个简单的 bash 脚本来计算已用内存的百分比,并在内存使用百分比超过 90% 时发送电子邮件。

这是我到目前为止的 bash 脚本。

#!/bin/bash
top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 7-14 
USEDMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 25-31
$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'
$USEDPCT | mail -s "Test Email from MOD Server" test@test.com

当我保存并执行脚本时,我收到错误“没有这样的文件或目录”:

-bash-3.2$ ./memcheck.sh
./memcheck.sh: line 4: =echo $USEDMEM / $MAXMEM * 100 | bc: No such file or directory
Null message body; hope that's ok
-bash-3.2$ 

有人可以帮忙吗?我是 bash 脚本的新手,这是我的第一个脚本。

谢谢

4

5 回答 5

4

其他答案的内容我不再赘述;top相反,当您需要的只是有关系统内存使用情况的信息时,我会质疑解析 的输出是否明智。

的输出top是供人类使用的,并且还包含许多不需要且生产成本高的每个进程的信息。的输出free更适合这种特殊用途。

其次,从脚本中的计算来看,您似乎不了解在 Linux 和其他类 Unix 系统上测量系统内存使用的方式。与其他操作系统相反,使用的内存大小包含用于磁盘缓存和其他缓冲区的内存。在任何已经运行了一段时间的系统上,可用内存趋向于零 - 未使用的内存是浪费的内存。

找出进程使用的内存量的第一步是从使用的内存大小中减去用于缓冲区的内存量。但即使这样在现代系统上也是不够的 - 甚至在一定程度free上会出错,正如我在这个较早的答案中top提到的那样。

于 2012-08-25T06:56:08.287 回答
2

你在这里有几个问题。

首先,这不会做你想做的事。

USEDMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 25-31

您不能将文件名通过管道传输到命令中。您实际上希望将文件的内容通过管道传输到命令中。你可以用“猫”来做到这一点。但是, grep 实际上是为在文件中搜索而设计的,因此您可以这样做

USEDMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 25-31)

请注意,$(cmd) 是您在子 shell 中执行命令的方式。即,您可以运行一些命令来计算脚本中变量的值。您也可以使用 `cmd`(反引号;通常在波浪号键上),但语法不太清楚。

同样,您可能希望在子外壳中计算此结果。另外,分配给变量时不要使用 $ 。

$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'

这可以重写为

USEDPCT=$(echo "scale=3; $USEDMEM / $MAXMEM * 100" | bc)

最后,您希望将变量的内容通过管道传输到邮件程序中。管道期望程序位于左侧。您可以通过将变量的值回显到管道中来做到这一点。

echo "$USEDPCT" | mail -s "Test Email from MOD Server" test@test.com

将所有内容重新组合在一起:

#!/bin/bash
top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 7-14)
USEDMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 25-31)
USEDPCT=$(echo "$USEDMEM / $MAXMEM * 100" | bc -l)
echo "$USEDPCT" | mail -s "Test Email from MOD Server" test@test.com
于 2012-08-25T04:02:04.243 回答
2

其他人已经指出您的代码存在问题,但对此有更简单的选择,即根本不解析top输出。使用/proc/meminfo, 和awk- 您将不需要临时文件。

$ awk '/MemTotal:/{total=$2} \
       /MemFree:/{free=$2} \
       END{ \
        print "Free mem percent: "(free*100/total); \
        print "Used mem percent: "((total-free)*100/total) \
       }' /proc/meminfo 

Free mem percent: 87.7348
Used mem percent: 12.2652

管它mail或任何你想要的。

于 2012-08-25T11:59:01.620 回答
0

我已经纠正了你的语法错误。PL。注意命令替换的使用,就像你写的一样

MAXMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 7-14.

这是错误的,你需要写

 grep "Mem" /home/modadm/top-output.txt | cut -c 7-14

然后将其括在反引号(制表键左侧的键)中,以将最终值分配给变量。你也写过,

$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'

美元符号使用错误。$ 应该在使用变量的值时使用。引号应该是 `(反引号)而不是 '(单引号)。反引号表示命令将被命令的输出替换。同样对于浮点 bc 需要设置比例。

PL。查看修改后的代码。希望这可以帮助。PL。注意我没有检查邮件命令的功能,如果它正在发送邮件。

top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=`grep "Mem" /home/modadm/top-output.txt | cut -c 7-14`
USEDMEM=`grep "Mem" /home/modadm/top-output.txt | cut -c 25-31`
USEDPCT=`echo   "scale=2; $USEDMEM / $MAXMEM * 100" | bc `
echo $USEDPCT | mail -s "Test Email from MOD Server" test@test.com
于 2012-08-25T04:00:06.127 回答
0

试试下面的脚本。

#! /bin/bash

memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`

USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`%

echo $PERCENTAGE | mail -s "Test Email" test@test.com
于 2012-08-25T04:02:41.900 回答