The problem: Bad responsiveness caused by high I/O load
On a typical desktop PC, there are several long-running tasks with a high I/O load which usually need to be executed regularly — like backups, indexing files for search, checking the backups, etc. Tasks with high I/O load however can cause bad responsiveness of the system under Linux, which results in applications being frozen, the mouse cursor not moving, etc.
With the most systems this can usually be fixed by selecting the CFQ scheduler
in the kernel. If you are running particular new hardware however, this might
not work since e.g. the kernel does not support setting an I/O scheduler for
those new fancy m.2 SSDs. Running an application like
borgbackup on one of those disks can completely fubar the desktop until
they are done.
To work around this problem, I've created the following script:
#!/bin/bash # execute-idle.sh # Copyright (C) 2018 Philipp Ludwig, <idle (at) philippludwig.net> # License: GPLv3 export DISPLAY=:0.0 set -e if [ "$1" == "" ]; then echo "Error: No command given" exit 1 fi $@ & PID=$! if [ "$PID" == "" ]; then echo "Could not determine PID of $1!" exit 1 fi kill -SIGSTOP $PID for p in $(ps --ppid $PID -ho '%p'); do kill -SIGSTOP $p; done while kill -0 $PID &> /dev/null; do sleep 5 if [ "$(xprintidle)" -gt 30000 ]; then # 30 seconds signal="-SIGCONT" else signal="-SIGSTOP" fi kill $signal $PID for p in $(ps --ppid $PID -ho '%p'); do kill $signal $p; done done
It is called
execute-idle.sh and designed to run these tasks only while
you are not using the computer (e.g. when you are in the kitchen for 10 minutes,
waiting on the cup of coffee).
Dependencies: xprintidle, bash
How it works
execute-idle.sh first starts the task specified as an argument, then pauses
it immediately by sending a
SIGSTOP. Then it calls
xprintidle every 5
seconds to check if you are still using the computer — if not, it sends a
SIGCONT signal to the process and all of its children, letting the job
continue. As soon as you return and type on your keyboard or move your mouse,
execute-idle.sh again sends
SIGSTOP to the process and its children,
pausing the task until you are idle again.
How to use it
Just put it in your crontab like this:
0 12 * * * ~/tools/execute-idle.sh ~/my-backup-script.sh
You might think that this causes some jobs to never finish, but after using this
script for several weeks I didn't encounter any problems like this. Due to the
rather short 5 second interval,
execute-idle.sh can utilize even small breaks
of e.g. 30 seconds.
Try running your backup with it — your regular backup check job should tell you if something went wrong.