What's the simplest way you know? Using any tool
In the beginning of your script, just touch a flag somewhere, so that subsequent invocations of that script can check for the existence and age of that flag.
There's some ambiguity in your question. So first, let's assume that you're asking "How to make a script execute only if certain amount of time has passed since the last time the script executed."
#!/bin/bash flag="/var/tmp/$(basename -- $0).flag" min_age=$(( 60 * 60 * 24 )) # 24 hours if [ -e "$flag" ] ;then (( $(date +%s) - $(date +%s -r "$flag") > min_age )) || exit 1 fi touch "$flag" # Proceed with your script # ...
But if you're asking "How to make a script execute only if it has not already been executed since midnight"...
#!/bin/bash flag="/var/tmp/$(basename -- $0).flag" if [ -e "$flag" ] ;then [ $(date +%F) = $(date +%F -r "$flag") ] && exit 1 fi touch "$flag" # Proceed with your script # ...
And if you're simply asking "How to run a sctipt at shutdown" -- then that varies widely from distro to distro. You'll most likely need to look into
/etc/rc6.d. On my system, for example, I have
/etc/rc.d/rc.local_shutdown, where I can add stuff. You'll need to mention what distro you're using.
Or check out this thread... Execute a command before shutdown
Simplest is largely a matter of opinion, but I feel the simplest way to do this is to use
cron. You will need some other "ingredients" to accomplish your objective, but
cron can serve as the scheduler for starting a script at
boot time. This assumes the version of
cron on your system offers the
@reboot facility; see
man 5 crontab to verify the "special" strings are allowed (
That said, using
cron is as simple as editing your user's
crontab. From your
bash command line:
$ crontab -e
This will open your
crontab in your default editor. Add the following line:
@reboot sleep 15; /path/to/your/script >> /path/to/your/iofile.txt 2>&1
This runs your script each time your system boots.
crondoesn't know the status of any services required in your script, the
sleep 15command is used to give the OS 15 seconds to marshal all required system resources. You may need more or less than this, depending on the resources needed, and other variables.
Use full path specifications in your
crontabas the environment (in particular the
PATH) is different than in your interactive shell.
Script output that would go to
stdoutshould be re-directed to a local file (iofile.txt here). The iofile.txt file will provide an easy way to access any errors thrown by your script - very helpful for debugging!
You have asked that a condition be applied to running your script
@reboot: "but only if it has not already been executed today" . This is taken to mean that there is a possibility that the script may have been executed manually by a user, or that the system may have been re-booted previously in the same day.
Meeting that condition of course depends on your definition of "today"; i.e. "today" as in the past 24 hours, or "today" as in on this same date.
For the case that
today=24 hours or less, your condition may be satisfied as follows:
#!/bin/bash LAST_BOOT=$(cat /path/to/your/timestamp.txt) CURRENT_BOOT=$(date +%s) ELAPSED_TIME=$((CURRENT_BOOT - LAST_BOOT)) echo $CURRENT_BOOT > /path/to/your/timestamp.txt # test ELAPSED_TIME < threshold if [ $((ELAPSED_TIME <= 86400)) ]; then exit; fi # the balance of your script follows...
Note use of the
+%s format for
date gives the epoch time; this allows us to subtract the two boot times to check for 24 hours (86,400 seconds).
For the case that
today=same date, your condition may be satisfied as follows:
#!/bin/bash LAST_BOOT=$(cat /path/to/your/timestamp.txt) CURRENT_BOOT=$(date +%d) # test for same date if [ $((CURRENT_BOOT = LAST_BOOT)) ]; then exit; fi # the balance of your script follows...
date +%d format provides the date only. We test for equality between the last boot time, and the current time in the
if statement which means that the script has already been run on this date.
After considering all of your comments just now, you may wish to consider
anacron. It's not in as wide use as
cron, but it does have the advantage that its
@daily schedule "will move tasks to different moments so they are run when the system is on". You may also wish to compare its advantages, and its disadvantages compared to
cron. If you wish to dig deeper, this may help
You could consider using anacron.
Anacron allows scheduling periodic jobs on computers that are not turned on all the time. To achieve this, it maintains so-called timestamp files that record the last time a job was run. When the computer is on, anacron regularly gets triggered via various mechanisms (startup script, regular cron jobs, systemd timers) and kicks off jobs that are due based on the timestamp files.
With anacron, in order to run a command once per day, you need to put a line like this into
@daily 0 daily-job command
The first field is the frequency and can be
@monthlyas well as an arbitrary number of days (e.g.,
2for every 2 days).
The second field is the delay to start running the job after anacron gets triggered.
The third field is the name of the job.
Finally, the fourth field is the command to execute.
On Debian derivatives, you can drop a script into
/etc/cron.daily instead, since anacron (if installed) takes over the task of running daily, weekly and monthly cron jobs by default.
Another option is fcron, which allows doing the same (and possibly more), but I do not have personal experience with it.