I have a cron job that calls a script that checks for updates once every hour. If there are updates, it will call update.sh
, which in turn calls commands.sh
. I would like each “new” commands.sh
to be run exactly once.
I was thinking of writing to a file each time I run commands.sh
with some unique ID of that file. Before running commands.sh
, I check if the file contains the ID of commands.sh
. If so, don’t run it.
Edit – more detail:
cronjob:
- fetch from git repo, pull and merge if any changes
Run
update.sh
:#!/bin/sh ./commands.sh
I want ./commands.sh
to run just once, because next hour, the cron will run again, pull from git, and run update.sh
again. Is there some way for each unique ./commands.sh
to run just once?
After writing that out, maybe the best way is just to only run update.sh
if there was a change from the git repo?
This seems like overkill and hard to maintain. Is there a simpler way to write a bash script that only runs one time?
Advertisement
Answer
At the start of the commands.sh
script do this:
if [ -f stampfile ]; then exit if touch stampfile
This checks for a file called stampfile
(specify a path to anywhere convenient where this may be stored). If it’s there, just exit
. If it’s not there create it with touch
.
Then let the script do its thing.
A slight digression: This can also be used to avoid having two instances of a script running at the same time. The script would then rm -f stampfile
at the end of its run.
In this case, if the script is killed, the stampfile
will be “stale” (stamp present but script not alive). To detect a stale stampfile
, put the PID of the script into it instead of touching it.
To check if there’s another instance running, and managing the stampfile:
if [ -f stampfile ]; then if kill -0 $(<stampfile) 2>/dev/null; then exit else rm -f stampfile # stale fi fi echo $$ >stampfile # rest of script rm -f stampfile
User @CharlesDuffy points out that this way of managing the stampfile
may be prone to PID reuse issues, i.e. that the PID in a stale stampfile
might be that of a running process that has nothing to do with any of this. There is apparently a Linux utility called flock
that allows you to do this in a more robust way.