一行脚本来检查并响应内存使用情况

一行脚本来检查并响应内存使用情况

我想要一行 shell/bash 来执行如下操作:

test "`free | grep | awk | whatever` -gt 80" && any_command

其中总内存百分比整个系统正在使用的与硬编码数字(在我的情况下是 80)进行比较。只要 RAM 高于给定的百分比,就执行,这test并不重要。any_command

  • 可以使用精确的字节/兆字节而不是百分比
  • 这应该适用于典型的 ubuntu 14.04
  • 旨在用作 cron 任务
  • 奖金:一行代码做同样的事情,但检查特定进程的内存

更新

有答案说这个问题是 monit/bluepill/god 之类的东西要解决的。我 100% 同意,你很可能应该遵循这些答案中的建议。然而,这个问题具体是关于我描述的那条线,无论出于什么原因,假设这可能涉及的所有注意事项和问题。

答案1

怎么样:

[ $(free -m| grep  Mem | awk '{ print int($3/$2*100) }') -gt "80" ] && echo "greater " || echo "lesser"

对于流程消耗,以下是解决方案的可能部分:

for p in $(pgrep bash); do total=$(($total + $(awk '/VmSize/ { print $2 }' /proc/$p/status))); done ; echo "Total memory usage: $total kb" ; unset total

将两者结合起来就留给读者作为练习。

答案2

不要重新发明轮子:)

监视实用程序是专门为处理这种情况而设计的。它有据可查并且有很多ServerFault 上的示例

  check system kale.GreenLeaf.com
    if loadavg (5min) > 16 for 15 cycles then alert
    if memory usage > 92% then alert
    if swap usage > 10% then alert

或者对于一个过程:

check process cups
    with pidfile "/var/run/cupsd.pid"
    start program = "/sbin/service cups start"
    stop program = "/sbin/service cups stop"
    if 10 restarts within 11 cycles then timeout
    if total memory > 1000.0 MB for 5 cycles then alert
    if total memory > 2000.0 MB for 5 cycles then restart
    if cpu usage > 95% for 11 cycles then restart

除了警报或启动/停止/重新启动操作之外,您还可以配置 EXEC:

EXEC 可用于执行任意程序并发送警报。如果选择此操作,则必须声明要执行的程序,如果程序需要参数,则必须将程序及其参数括在引号字符串中。您可以选择指定执行的程序在启动时应切换到的 uid 和 gid...

if total memory > 2000.0 MB for 5 cycles then exec "/sbin/service sidekiq restart"

答案3

你到底想做什么?你可能在尝试做错事。

[ $(free | perl -nE 'if (/Mem/) { (undef,$total,$used) = split; say int(100*$used/$total) }') -gt 80 ] && echo foo

但请注意,无论你试图用它实现什么几乎肯定无用(甚至可能有害)。没有“正在使用的 RAM 百分比”这样的东西。是的,free它会显示有多少内存是“空闲的”,但这可能并不意味着你认为的那样(该字段最好命名为“浪费的”或“你不应该购买的内存量”)。

例如,内核不会在内存中“加载”程序,而是映射它们,因此一些数百 MB 的示例程序将能够在仅 12KB 的内存中运行。此外,所有访问的文件都将缓存在同一内存中(称为页面缓存)——过去运行的程序(因此如果再次运行,其文件将被缓存)或过去读取/写入的数据文件(因此如果再次访问它们,它们将更快)之间没有区别

因此,如果您的磁盘空间大于内存空间(这种情况很常见),您的“可用”(又称“浪费”)内存在启动后将迅速收敛到接近 100%(实际上更像是 80-95%,因为内核会尝试保留部分可用空间,以便在内存压力大时可以快速访问)。这是正常的,而且实际上是需要的,因为它将大大加快您对磁盘的访问速度(在最佳情况下),或者如果没有东西再次访问相同的文件(最坏情况),它与“可用内存”一样好。

所以你真的想避免拥有“空闲”的内存(在占用大量内存的程序终止后有时会发生这种情况)。

編輯1:此外,上述结果只是可能的(完全不同的)答案,因为这样的问题是未定义的。例如,您可以使用“Mem used-cached”(当您减去磁盘缓存时,它将显示使用了多少内存)而不是“Mem used”(这将显示使用了多少内存)——这可能会给您“15%”而不是“80% used”这样的结果,并且可能更准确——具体取决于您到底想要实现什么

至于进程内存使用情况,同样的事情——有太多方法可以说明进程使用了​​多少内存。是程序所需的量(ps输出中的 VSZ)。还是当前 RAM 中的数量(RSS 列)。当有多个共享代码的实例时会怎样(例如,如果您有 100 个 apache 进程,每个进程的 RSS 为 50MB,它们不会使用 100*50 = 5000MB RAM,而是总共使用 200MB),等等。当您确切知道自己想要什么时,您才能继续计算它(仅 VSZ、仅 RSS、RSS-shared、RSS-shared/num-of-processses-sharing 等)

另请注意,此类问题更侧重于超级用户网

编辑2:至于您的评论,您正在尝试避免某些进程发生内存泄漏。检查可用内存肯定是错误的,因为它会给出误报。您应该限制您的进程,以防止内存泄漏导致系统其余部分崩溃(参见help ulimitbash)。进程可能会处理该问题(好)或在无法获得所需内存量时死亡,因此您可以重新启动它(通过 monit、supervise、runit 或类似方法)

编辑3:除了(或者作为替代,但实际上更好的补充)设置进程限制之外,当 RSS 变得太大时,您可以使用类似这样的方法重新启动进程。

[ $(awk '/^VmRSS/ { print $2}' /proc/$PID/status) -gt 200 ] && echo killmeplease

当然,$PID您不会使用您的 PID(例如来自PID=$(cat /var/run/something.pid)PID=$(pidof somedaemon)等等)。

但请注意,您最好使用VmSize(或VmPeak)而不是(VmRSS),否则,如果您的进程进入交换区,仍然会导致系统崩溃(因此 VmSize 会很大,而 VmRSS 会很小)

相关内容