-2

我有一个小问题。我需要解释一下,awk 是什么。

我需要编写一个脚本来监视系统上的负载是否过载(CPU、RAM)并写入消息。

我有这个:

if 
[[ $(bc <<< "$(top -b -n1 | grep ^Cpu | awk -F': ' '{print $2}' | awk -F% '{print $1}') >= 100") -eq 1 ]] ; then echo '...'; 
fi

这是针对 CPU 的。谁能解释一下这个例子中的 awk 是什么?RAM 的 awk 会怎样?

4

2 回答 2

0

第一次 awk 调用将在任何行打印第二个标记,其中标记由冒号或空格分隔。

第二个将打印标记由百分号 (%) 分隔的任何行中的第一个标记。

在 Linux 系统上获取已用内存:

free | awk '/Mem:/ {print $3;}'
于 2012-11-28T16:21:13.800 回答
0

这是一个非常脆弱的脚本,基于看起来像旧版本的top。不过,检查这段脚本非常容易 - 所以,让我们来看看它。我们从以下内容开始:

top -b -n1

哪个(阅读top的手册)将top置于批处理模式(这意味着我们不想与top交互播放,而是希望将输出发送到另一个命令)并输出 1 次迭代。这将使我们得到如下输出:

$ top -b -n1
top - 10:48:33 up 1 day, 22:51,  3 users,  load average: 1.21, 1.27, 1.03
Tasks: 262 total,   2 running, 260 sleeping,   0 stopped,   0 zombie
%Cpu(s): 14.5 us,  5.2 sy, 11.3 ni, 67.3 id,  1.6 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem:   8124692 total,  6722112 used,  1402580 free,   384188 buffers
KiB Swap:  4143100 total,   430656 used,  3712444 free.  2909664 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
11012 user1     20   0  426412  14436   5740 R  97.1  0.2  19:27.98 dleyna-renderer
 4579 root      20   0  286480 152924  31152 S  13.0  1.9  24:15.49 Xorg
    1 root      20   0  185288   4892   3352 S   0.0  0.1   0:02.52 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
    3 root      20   0       0      0      0 S   0.0  0.0   0:02.77 ksoftirqd/0
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
    7 root      20   0       0      0      0 S   0.0  0.0   1:32.00 rcu_sched

当我们将其通过管道传递给grep ^Cpu ... 时,我们似乎发现了一些破损,表明我们在此答案中使用的top版本可能与原始脚本预期的版本不同。看起来意图是在^%Cpu上进行匹配。这是更正后的部分:

$ top -b -n1 | grep ^%Cpu
%Cpu(s): 14.6 us,  5.2 sy, 11.2 ni, 67.3 id,  1.6 wa,  0.0 hi,  0.1 si,  0.0 st

管道的下一部分是摆脱'%Cpu(s): '部分:

$ top -b -n1 | grep ^%Cpu | awk -F': ' '{print $2}'
15.1 us,  5.0 sy, 10.8 ni, 67.4 id,  1.6 wa,  0.0 hi,  0.1 si,  0.0 st

然后下一段...... awk -F% '{print $1}' - 对于这个答案的top版本再次没有意义,因为脚本正在寻找打印%符号左侧的内容 -我们的输出中没有%。所以......我们不知道我们需要从这里去哪里。

从脚本的其余部分...管道的结果与 100 进行比较...因此,我假设脚本要解析的top版本在第一列中占 CPU 利用率总数的百分比...在我们的顶级输出版本中,所有输出的粒度都更加精细。以下是前一个输出的细分:

 15.1% -- spent in normal priority user/applications
  5.0% -- spent in system/kernel
 10.8% -- spent in low priority batch or daemon jobs
 67.4% -- spent "idle"
  1.6% -- spent waiting for I/O to complete
  0.0% -- spent in servicing HW interrupts
  0.1% -- spent in servicing software interrupts
  0.0% -- spent stolen by another VM running on the HW
------------------------------------------------------
100.0% -- Total

...因此,在现代 Linux 系统上,top提供了更多信息,也许我们需要以不同的方式看待问题。在这种情况下,我们可以将 (idle * 10) 视为度量——就像在 shell 中一样,我们只有整数数学和比较可供我们使用。所以,我们将稍微调整一下脚本......在我们处理它的同时,让我们摆脱管道中的grep,因为这也可以通过awk轻松完成:

$ top -b -n1 | awk -F, '/^%Cpu/ {print $4}'
 67.8 id

现在让我们调整它,让它只给我们乘以 10 的空闲值:

$ top -b -n1 | awk -F, '/^%Cpu/ { sub(/id/,"",$4); print $4*10 }'
678

好的,原始脚本的下一部分使用bc来查看我们是否被 100% 使用。由于我们现在关注的是空闲而不是利用率,因此我们想要与原始脚本相反。此外,由于输出被缩放为整数,我们不需要bc的复杂性。让我们在比较中使用shell?

$ if [ $(top -b -n1 | awk -F, '/^%Cpu/ { sub(/id/,"",$4); print $4*10 }') -le 0 ]; then echo '...'; fi

就是这样。

这个答案完全是为了展示代码是如何工作的——如何通过管道解释和解析top的输出,如何执行弄清楚一段脚本的作用,以及如何修复脆弱/损坏的脚本。然而,原始脚本不仅脆弱,而且在设计上几乎被破坏了。我们用来检测过载系统的指标更像是在top命令输出的第一行中找到的“平均负载”,甚至可以从uptime命令的输出中解析出来。

找出过载的一种方法可能是查看负载平均值除以 CPU 的数量。可以通过解析 /proc/cpuinfo 轻松找到 cpu 的数量:

$ grep ^processor /proc/cpuinfo | wc -l
4

这是一个示例,其中 15 分钟内的 400% 负载被视为连续负载阈值:

load=$(uptime | awk -F, '{ print $(NF) * 1.0 }')
proc=$(grep ^processor /proc/cpuinfo | wc -l)
plod=$(awk "BEGIN { x = 100 * $load / $proc; print int(x) + int(x+x)%2 }")

if [ $plod -gt 400 ]; then echo '...'; fi

注意:int(x) + int(x+x)%2是一个舍入函数

对于系统上的可用内存量,我喜欢schtever的回答——除了我会使用第 4 列而不是第 3 列并检查内存是否不足。

于 2015-11-17T21:55:29.490 回答