我想要一行 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 ulimit
bash)。进程可能会处理该问题(好)或在无法获得所需内存量时死亡,因此您可以重新启动它(通过 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 会很小)