简体   繁体   English

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

[英]run cron job only when machine is idle (linux)

How can I run a cron job(bash script) only when CPU idle >50%? 如何在CPU空闲> 50%时运行cron作业(bash脚本)?

I can get cpu idle from TOP 我可以从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

my current setup is: 我目前的设置是:

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.

And I have the PHP script check for CPU idle: 我有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

The problem with my current method is it starts the program regardless of CPU utilization. 我当前的方法的问题是无论CPU利用率如何都启动程序。 And the while loop running TOP feels not efficient. 运行TOP的while循环感觉效率不高。 I wish it only starts when CPU idle>50 我希望它只在CPU空闲> 50时启动

Some additional info: 一些额外的信息:

  • Centos 6.2, PHP5.3 Centos 6.2,PHP5.3

  • I have a few EC2 instances that never shuts down, so I want to utilize their processing power when idle. 我有一些永不关闭的EC2实例,所以我想在闲置时利用它们的处理能力。 But never load the server heavily. 但永远不要大量加载服务器。 (redundancy DB instance, Development instance, NAT instance) (冗余数据库实例,开发实例,NAT实例)

  • I know EC2 auto scaling, spot instance. 我知道EC2自动缩放,现场实例。 Just want to use the extra capacity. 只是想使用额外的容量。

  • the background job is image compression (CPU intensive, not much I/O or network). 后台作业是图像压缩(CPU密集型,I / O或网络不多)。

Any suggestion is welcome. 任何建议都是受欢迎的。 thanks in advance! 提前致谢!


Based on the input below, I realized that "nice" is a better solution in my case. 根据下面的输入,我意识到“好”是我个案中更好的解决方案。 I should re-align my objective to minimize impact to the server instead of tracing CPU utilization. 我应该重新调整我的目标,以尽量减少对服务器的影响,而不是跟踪CPU利用率。

So the new setup is: 所以新的设置是:

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

And PHP script: 和PHP脚本:

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

I'll test it and post back my finding. 我会测试它并回复我的发现。


report back: I have put this code through DEV/PRD, it works quite well. 报告回来:我把这段代码放到DEV / PRD上,效果很好。 It does not solve the problem of TOCTOU but is good enough for now. 它没有解决TOCTOU的问题,但现在已经足够好了。

This is a typical case of TOCTOU - you check if the system is idle, and start your process - but after your check, as or before your process starts, something else caused another process in the system to kick off and you still load the system more than necessary. 这是TOCTOU的典型案例 - 您检查系统是否处于空闲状态并启动您的流程 - 但在检查之后,在流程开始之前或之前,还有其他因素导致系统中的另一个流程启动,您仍然会加载系统超过必要的。

The "correct" way to do this is to give your process a low priority, using the nice command. 执行此操作的“正确”方法是使用nice命令为您的进程提供低优先级。 By the way, your loop to check cpu usage will use 100% cpu, so it probably wouldn't work unless THE FIRST time you check it's idle. 顺便说一句,你检查cpu使用的循环将使用100%cpu,所以它可能无法工作,除非你第一次检查它是空闲的。

You already have a "proc_nice(10)", so that should do the job. 你已经有了一个“proc_nice(10)”,所以应该做这个工作。 I don't see any point in spending effort in identifying whether the system is busy or not. 我没有看到花费精力来确定系统是否繁忙。

If you watned to, at suitable points in your code, you could do something like: 如果您在代码中的适当位置注意到,您可以执行以下操作:

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

But I'm not sure if that's much use - if the system is busy, a "nice" process won't receive much CPU-time, and thus won't compete with other processes that run at higher priority. 但是我不确定这是否有用 - 如果系统繁忙,“好”的进程将不会获得太多的CPU时间,因此不会与其他以更高优先级运行的进程竞争。

If you simply wish to have your script executed whenever the system load is eg 2.0 or less, you could use a shell script like this: 如果您只是希望在系统负载为2.0或更低时执行脚本,则可以使用如下的shell脚本:

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

Save it as eg /usr/local/bin/if-idle , and stick if-idle in front of your command in your crontab file. 将其保存为例如/usr/local/bin/if-idle ,并在crontab文件中的命令前面保留if-idle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM