start job when cpu is idle

with batch a command/process is started – when the CPU Load average gets below 0.8 = 80%

but as you will see later – you can also make your own script to set your own thresholds.

cat /proc/loadavg; # examples: 1.00 = 100%, 0.3 = 30%
0.30 0.74 0.71 1/256 2942
 \     \    \_15 minutes load average
  \     \_ 5 minutes load average
   \_1 minute load average
# switch to terminal1: (Ctrl+Alt+F1)

### create cpu stressing script

vim; # create test script
# causes 100% cpu usage by pringint useless output :-D
while true; do
  echo -n "+.";

ESC :wq # save and quit vim

chmod u+x; # mark it runnable

### create a second load average monitoring script

echo "while true; do cat /proc/loadavg; sleep 1; done;" >; # second script
chmod u+x;

nohup ./ & # run it in background
./; # monitor cpu load average levels

# you could alternatively use

htop; # start htop (if not installed: apt-get install htop;), in htop in the top right corner you see "Load average: 0.89"

# switch to terminal2: (Ctrl+Alt+F1)

touch this_file_will_be_created_when_idle;
wall "your system is idle";
# Ctrl+D - save and quit

# strangely - first time i try to wall - it get's run immediately after quit
# second time - it takes some time - but also starts (despite CPU load average being pretty high all 3 values) 1.00 1.00 0.90 2/257 3479
# if cpu goes down for a few seconds - it might be enough to trigger the job
# eventuelly the task does not start until you switch back to terminal1 and cancel the job

run task when 1min 5min or 15min-cpu-load-average reaches threshold

it might be wise to write your own script – that monitors the third load average level (15minutes) and when this stays below a certain value – run your stuff.

note! this script is incomplete… there needs to be OBSERVE_TIME during which the average load is just observed – and if not above THRESHOLD the command is started – otherwise the loop resets max-value and observes another 5 minutes.

vim /usr/local/bin/if-idle; # create script that does that

# TODO: implement OBSERVE_TIME
# monitors the 15min-cpu-load-average of /proc/loadavg and runs passed command when below THRESHOLD

THRESHOLD=0.5 # set threshold
OBSERVE_TIME=5 # how many minutes to observe the system, if values above threshold are seen, command won't start

while true; do
        # LOAD=`cat /proc/loadavg | cut -d" " -f1`; # if you want to use the 1 min load average value
        # LOAD=`cat /proc/loadavg | cut -d" " -f2`; # if you want to use the 5 min load average value
        LOAD=`cat /proc/loadavg | cut -d" " -f3`; # if you want to use the 15 min load average value

        echo "15min-cpu-load-average: "$LOAD;
        echo "THRESHOLD:              "$THRESHOLD;

        if [ ${LOAD%.*} -eq ${THRESHOLD%.*} ] && [ ${LOAD#*.} \> ${THRESHOLD#*.} ] || [ ${LOAD%.*} -gt ${THRESHOLD%.*} ]; then

                echo "system is busy - waiting for 15min-cpu-load-average to come down";

                echo "system is idle - will run your command now";

        sleep 1;

ESC :wq # save quit vim

chmod u+x /usr/local/bin/if-idle; # mark it runnable

### test the script
if-idle echo "run now this and that when idle";

15min-cpu-load-average: 0.32
THRESHOLD:              0.3
system is busy - waiting for 15min-cpu-load-average to come down

# depending on your previous load this might take a long time for it to come down :-D

15min-cpu-load-average: 0.29
THRESHOLD:              0.3
system is idle - will run your command now
run now this and that when idle


Save it as e.g. /usr/local/bin/if-idle, and stick if-idle in front of your command in your crontab file.

thanks chrishoj:

also niceness helps to asign priorities to your tasks.