I want to run a script once day (and only on weekends), however, I cannot use cron job for that.
I was thinking about having an infinite while loop, sleep for 24 hours, check if it is a weekend, and if so execute the script.
What it's a goo开发者_如何学编程d solution under bash on linux?
my current implementation:
#! /bin/bash
while [ true ]; do
if [[ $(date +%u) -lt 6 ]]; then
./program
else
echo Today is a weekend, processing is skipped. Back to sleep.
fi
sleep 86400
done
And I will launch this script at 5 pm.
Back in the day when there were no per-user crontabs, I often accomplished this using at(1).
#!/bin/sh
... do stuff...
at -f /path/to/me 5pm tomorrow
This way your script runs and schedules itself for the next invocation.
I don't think you can specify a timespec of "next weekend", so you'll just have to reschedule every day and have your script exit (after scheduling the next at job) if it is not a weekend.
Edit: Or instead of scheduling every day, find out what today is and schedule appropriately. e.g.
day=Saturday
if [ $(date +%u) -eq 6 ] ; then day=Sunday ; fi
at -f /path/to/me 5pm next $day
If this script is run on a Saturday, it schedules the next run for next Sunday, otherwise it runs next Saturday. [ $(date +%A) = Saturday ]
may be more readable, buts %A will give a locale-specific string so may not work if you change locale.
For a Perl solution then take a look at Schedule::Cron
CPAN module:
use 5.012;
use warnings;
use Schedule::Cron;
my $cron = Schedule::Cron->new( sub {} );
# add weekend run @ 05:00
$cron->add_entry('0 5 * * Sat,Sun', sub {
system './program';
});
$cron->run();
Assuming you really can't use cron or at to schedule jobs you will need to write a sleep loop. The details of how you write it will vary based on your requirements.
If you only want to execute once a day you have to worry about short sleeps. The sleep system call that is underneath most languages sleep function doesn't assure you that it will sleep the requested length of time. Your program might sleep for slightly longer than requested or much shorter than requested. You can schedule a sleep for 24 hours, but the OS may wake your program to deliver a signal after a few hours or even after only a few seconds. If your not keeping track of the last run, or your next expected run you can execute multiple times a day.
If you want to execute at a specific time you will need to vary the length of time you sleep. A partial sleep might set you off by half a day and you will need to sleep 12 hours to get back in sync.
You need to account for Daylight Saving/Summer Time. One day a year will have 23 hours, and another will have 25.
You can use something along the lines of this pseudocode:
set next_time_to_run
loop forever
sleep time_difference_in_seconds(current_time, next_time_to_run)
if current_time is close to next_time_to_run
execute code
update next_time_to_run
end if
end loop
The problem with using a long sleep
is that your program's idea of what time it is will drift. It would be better just to loop with short sleep
periods and check to see if you're within the desired window.
If your admins don't allow you to use cron
, they may not be happy that you're circumventing that restriction.
However, here's a rough outline:
while :
do
dow=$(date +%u)
if (( dow == 6 || dow == 7 ))
# you can check a flag or counter to limit the number of times it's performed
# or use a more refined date spec than just whole days (times of day, in other words)
then
do_something
sleep 1h # or use a smaller or larger interval
fi
done
You can use snaked. It is similar to cron, but written in Perl.
精彩评论