Handle “race-condition” between 2 cron tasks. What

2019-08-03 02:16发布

I have a cron task that runs periodically. This task depends on a condition to be valid in order to complete its processing. In case it matters this condition is just a SELECT for specific records in the database. If the condition is not satisfied (i.e the SELECT does not return the result set expected) then the script exits immediately.
This is bad as the condition would be valid soon enough (don't know how soon but it will be valid due to the run of another script).
So I would like somehow to make the script more robust. I thought of 2 solutions:

  1. Put a while loop and sleep constantly until the condition is valid. This should work but it has the downside that once the script is in the loop, it is out of control. So I though to additionally after waking up to check is a specific file exists. If it does it "understands" that the user wants to "force" stop it.
  2. Once the script figures out that the condition is not valid yet it appends a script in crontab and stops. That seconds script continually polls for the condition and if the condition is valid then restart the first script to restart its processing. This solution to me it seems to work but I am not sure if it is a good solution. E.g. perhaps programatically modifying the crontab is a bad idea?

Anyway, I thought that perhaps this problem is common and could have a standard solution, much better than the 2 I came up with. Does anyone have a better proposal? Which from my ideas would be best? I am not very experienced with cron tasks so there could be things/problems I could be overseeing.

2条回答
甜甜的少女心
2楼-- · 2019-08-03 02:32

Following up from our conversation in comments, you can take advantage of conditional execution in a cron entry. Supposing you want to branch based on time of day, you might use the output from date.

For example: this would always invoke the first command, then invoke the second command only if the clock hour is currently 11:

echo 'ScriptA running' ; [ $(date +%H) == 11 ] && echo 'ScriptB running'

More examples!

To check the return value from the first command:

echo 'ScriptA' ; [ $? == 0 ] echo 'ScriptB'

To instead check the STDOUT, you can use as colon as a noop and branch by capturing output with the same $() construct we used with date:

: ; [ $(echo 'ScriptA') == 'ScriptA' ] && echo 'ScriptB'

One downside on the last example: STDOUT from the first command won't be printed to the console. You could capture it to a variable which you echo out, or write it to a file with tee, if that's important.

查看更多
smile是对你的礼貌
3楼-- · 2019-08-03 02:39

instead of programmatically appending the crontab, you might want to consider using at to schedule the job to run again at some time in the future. If the script determines that it cannot do its job now, it can simply schedule itself to run again a few minutes (or a few hours, as it may) later by way of an at command.

查看更多
登录 后发表回答