仅在机器空闲时运行cron作业(linux)

时间:2013-01-14 19:57:33

标签: php linux bash cron centos

如果CPU空闲> 50%,我怎么能运行cron作业(bash脚本)?

我可以从TOP

获得cpu空闲
top -b -d 00.10 -n 3 |grep ^Cpu
Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

我目前的设置是:

crontab
0,15,30,45 * * * * /usr/bin/php /home/user/batchprocess.php
# I could use a bash script here to call PHP, if it is a good solution.

我有PHP脚本检查CPU空闲:

batchprocess.php
proc_nice(10);
// wait for CPU idle
do{
    $cpu_stat = exec('top -b -d 00.10 -n 3 |grep ^Cpu');    
    $tmp = stristr($cpu_stat,'%id',TRUE);
    $cpuidle = trim(substr($tmp,strrpos($tmp,',')+1));
}while($cpuidle<$min_cpuidle);
// do actual processing here

我当前方法的问题是无论CPU利用率如何,它都会启动程序。运行TOP的while循环感觉效率不高。我希望它只在CPU空闲&gt; 50

时启动

其他一些信息:

  • Centos 6.2,PHP5.3

  • 我有一些永不关闭的EC2实例,所以我想在空闲时利用它们的处理能力。但永远不要大量加载服务器。 (冗余数据库实例,开发实例,NAT实例)

  • 我知道EC2自动缩放,现场实例。只是想使用额外的容量。

  • 后台作业是图像压缩(CPU密集型,I / O或网络不多)。

欢迎任何建议。提前谢谢!


根据下面的输入,我意识到“好”是我个案中更好的解决方案。我应该重新调整我的目标,以尽量减少对服务器的影响,而不是追踪CPU利用率。

所以新的设置是:

crontab
0,15,30,45 * * * * nice -20 /usr/bin/php /home/user/batchprocess.php

PHP脚本:

batchprocess.php
if ($cpuidle < 50) 
    exit(0);
// do actual processing here

我会测试它并回复我的发现。


报告回来:我已经把这段代码放到DEV / PRD上了,它运作得很好。它没有解决TOCTOU的问题,但现在还不错。

2 个答案:

答案 0 :(得分:6)

这是TOCTOU的典型情况 - 您检查系统是否处于空闲状态并启动您的流程 - 但在检查之后,在流程开始之前或之前,还有其他因素导致系统中的另一个流程启动关闭,你仍然加载超过必要的系统。

执行此操作的“正确”方法是使用nice命令为您的进程提供低优先级。顺便说一句,你检查cpu使用的循环将使用100%cpu,所以它可能无法工作,除非你第一次检查它是空闲的。

你已经有一个“proc_nice(10)”,所以应该做这个工作。我没有看到花费精力来确定系统是否繁忙。

如果您在代码中的适当位置注意到,您可以执行以下操作:

 if (check_cpu_usage() > 50%) sleep(1second); 

但是我不确定这是否有用 - 如果系统繁忙,“好”的进程将不会获得太多的CPU时间,因此不会与其他以更高优先级运行的进程竞争。

答案 1 :(得分:1)

如果您只是希望在系统加载时执行脚本,例如2.0或更少,您可以使用这样的shell脚本:

#!/bin/sh
LOAD=`cat /proc/loadavg | cut -d" " -f1`
THRESHOLD=2.0
if [ $(bc <<< "$LOAD <= $THRESHOLD") -eq 1 ]; then
    $@
fi

将其另存为例如/usr/local/bin/if-idle,并在您的crontab文件中将if-idle放在命令前面。