Are there any established patterns for installing a kill or on/off switch for user cron jobs?

Solution 1:

Rather than messing with crond, I strongly suggest to implement some (even simple) form of locking inside your build scripts. For example, touch and check for a file in /var/run/: if your script find something, than another process is building the project. You obviously need to remove the lockfile when finished.

As @GnP noted in the comments, you can also use the flock utility for semi-automatically manage your lockfiles.

If you don't/can't rely on any locking mechanism, simple issue a service crond stop to shutdown the crond system.

Solution 2:

I tend to just wrap all long running commands in a screen and get cron to start the screen only if there is not one running already.

So the following line in crontab

*/2 * * * *  /bin/bash /path/to/LongRunningScript.bash

... turns into something like this:

*/2 * * * *  /usr/bin/screen -S MyUniqueName -Q select . || /usr/bin/screen -dmS MyUniqueName /bin/bash /path/to/LongRunningScript.bash

I like this because it also gives you the chance to attach to a running script and check its output / status.

In your scenario, you could get cron to check for another screen before executing a build, for example

0 3 * * *  /usr/bin/screen -S ManualBuild -Q select . || /usr/bin/screen -dmS AutomatedBuild /bin/bash /path/to/BuildScripts.bash
10 3 * * *  /usr/bin/screen -S ManualBuild -Q select . || /usr/bin/screen -dmS OtherAutomatedBuild /bin/bash /path/to/OtherBuildScripts.bash

When you run a manual build, just hop into a screen first before you run the script (please comment if you need hints how to connect / disconnect from screen. It is a useful utility - give it a shot if you have not started using it yet)

Type screen -S ManualBuild, hit [enter] and run whatever commands you want to run.

Note: If you use the example as supplied you might confuse cron if you have more than 1 screen session with a name of "ManualBuild" running.