Run cron job only when machine is inactive (linux)

How to run cron job (bash script) only when CPU is not working> 50%?

I can get cpu idle from TOP

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:

 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 a PHP script to idle the processor:

 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 that it runs the program regardless of CPU usage. And the while loop working in TOP seems inefficient. I want it to start only when the CPU is idle> 50

Additional Information:

  • Centos 6.2, PHP5.3

  • I have several EC2 instances that never close, so I want to use their processing power in standby mode. But never load the server hard. (redundancy DB instance, development instance, NAT instance)

  • I know EC2 autoscaling, point instance. I just want to use the extra capacity.

  • background work - image compression (processor intensity, not a lot of input-output or network).

Any suggestion is welcome. thanks in advance!


Based on the introduction below, I realized that β€œgood” is the best solution in my case. I have to redefine my goal to minimize the impact on the server, and not track CPU usage.

So, the new setting:

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

And a PHP script:

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

I will check it and send it back.


report: I put this code through DEV / PRD, it works very well. It does not solve the TOCTOU problem, but so far is good enough.

+4
source share
2 answers

This is a typical TOCTOU case β€” you check to see if the system is idle and start your process β€” but after you check how or before starting your process, something else caused another process to start on the system, and you still load the system more than necessary.

The β€œright” way to do this is to give your process a low priority using the nice command. By the way, your CPU usage check cycle will use a 100% processor, so it probably won't work if the FIRST time you check it at idle.

You already have "proc_nice (10)", so it should do the job. I see no reason to spend effort on determining if the system is busy or not.

If you looked at the appropriate points in your code, you could do something like:

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

But I'm not sure that if the system is busy, a β€œgood” process will not get a lot of processor time and, therefore, will not compete with other processes that work with a higher priority.

+6
source

If you just want your script to be executed whenever the system boots, for example. 2.0 or less, you can use a shell script as follows:

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

Save it, for example. /usr/local/bin/if-idle and insert if-idle before your command in the crontab file.

+1
source

All Articles