Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

My first solution to this was to execute date +%Y%m%d%H%M and put that format of numbers into a file, and run the script every minute from cron. Then if the date from the file matches the date command, the script would do something. Then it would update that file for the next day plus 3 minutes. Is there a better way to accomplish this?

The result would be that the script would run the first day at (for example) 4:00am then the second day it would run at 4:03am and the third day it would run at 4:06am. It would execute every minute, but only run (if block) at the correct time.

Is the question and my solution clear?

share|improve this question
add comment

migrated from stackoverflow.com Jun 4 '12 at 5:51

This question came from our site for professional and enthusiast programmers.

3 Answers

up vote 5 down vote accepted

You can use the at command from within your script (or a wrapper). Give it the time to run the next iteration.

echo '/dir/scriptname' | at 'now + 1443 minutes'

Put that line as near as possible to the beginning of the script to reduce drift.

share|improve this answer
    
That is a great solution! But wouldn't it need to be 'now + 24 hours + 3 minutes'? –  Elmer Jun 4 '12 at 4:54
    
@Elmer: Oops! You are correct (except that you can't do running addition). I'll edit my answer. –  Dennis Williamson Jun 4 '12 at 4:55
    
To avoid drift, tell the script what time it's supposed to run and let it add 24h 3m to that. –  Keith Thompson Jun 4 '12 at 5:06
    
@KeithThompson: But then you have to keep a counter and increment it. –  Dennis Williamson Jun 4 '12 at 5:27
    
Here's a script I wrote to reschedule at jobs. It's not pertinent to the question, but it's tangentially related. –  Dennis Williamson Jun 4 '12 at 5:32
show 1 more comment

You should use at instead of cron, it will allow you to run the task exactly once. It could then re-schedule itself.


Well, I'd like to suggest some improvement to your own solution - if you'd stick to it. It will, however, still require to run the script every minute via cron:

Instead of manipulating any setup or tracking when the script has run the last time, you could reach the same goal with the UNIX timestamp:

A day has 60*60*24 = 86400 seconds. If you add the 3*60 = 480 from your requirements, you have 86880 seconds - and that's exactly the interval you want your script to run. Inside the script you can now check whether the current UNIX time % (modulo) this number of seconds equals zero, and abort otherwise.

If you need to have an explicit first run, like the 5th of June, 2012, 4:00 AM, you can subtract the associated timestamp (1338861600) from the local time first, check that it's not less than zero and proceed with the difference...


Of course, you could also let the script modify it's own crontab entry, but that's risky and also kinda awkward.

share|improve this answer
    
Preferably it would run on boot/reboot and keep the correct sequence even in the case of a random reboot. Yes the script editing the crontab sounds risky... Can you explain more about Inside the script you can now check whether the current UNIX time % (modulo) this number of seconds equals zero, and abort otherwise. –  Elmer Jun 4 '12 at 5:00
    
The modulo operation returns the remainder from a division. So, if the reminder is zero, you know that the exact amount of seconds has been passed. See en.wikipedia.org/wiki/Remainder and en.wikipedia.org/wiki/Modulo_operation -- but this is just fancy stuff, I'd recommend the at command like Dennis did –  mjhennig Jun 4 '12 at 5:16
    
If you check the seconds, are you not risking that if the script check happens one second latter (maybe because the machine is doing a lot of work) it would "think" that it's not the right time to run? –  João Portela Jun 4 '12 at 10:21
    
Of course. But as I said, this is just a fancy way to go "because one can" - at is probably the correct choice here.. –  mjhennig Jun 4 '12 at 10:27
    
I thought I should warn in case someone wants to use it anyway. Since in that approach the script runs every minute, a 30 second interval after the target time seems reasonable ( UnixTime % 86880 < 30 )`. –  João Portela Jun 4 '12 at 10:37
add comment

You can modify your script to check some flag file with time to run at first. If time matches to start time, then your script goes on, otherwise it ends with exit 0. And you can start it in cron even every minute (or once at 3 minutes, seems it may be enough for your case). Also you need your script to modify time of next run in flag file. That safe enough and you won't miss any start time even in case of random reboot.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.