Bash – How to Execute Bash Script Every 3 Days

bashcommand linecronscripts

I want to execute a shell script literally after every 3 days. Using crontab with 01 00 */3 * *won't actually fulfil the condition, because it would run on 31st and then again on the 1st day of a month. The */3 syntax is the same as saying 1,4,7 … 25,28,31.

There should be ways to make the script itself check the conditions and exit if 3 days haven't passed. So crontab executes the script everyday, but the script itself would check if 3 days have passed.

I even found some code, but it gave me syntax error, any help would be appreciated.

if (! (date("z") % 3)) {
     exit;
}

main.sh: line 1: syntax error near unexpected token `"z"'
main.sh: line 1: `if (! (date("z") % 3)) {'

Best Answer

To immediately abort and exit a script if the last execution was not yet at least a specific time ago, you could use this method which requires an external file that stores the last execution date and time.

Add these lines to the top of your Bash script:

#!/bin/bash

# File that stores the last execution date in plain text:
datefile=/path/to/your/datefile

# Minimum delay between two script executions, in seconds. 
seconds=$((60*60*24*3))

# Test if datefile exists and compare the difference between the stored date 
# and now with the given minimum delay in seconds. 
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test -f "$datefile" ; then
    if test "$(($(date "+%s")-$(date -f "$datefile" "+%s")))" -lt "$seconds" ; then
        echo "This script may not yet be started again."
        exit 1
    fi
fi

# Store the current date and time in datefile
date -R > "$datefile"

# Insert your normal script here:

Don't forget to set a meaningful value as datefile= and adapt the value of seconds= to your needs ($((60*60*24*3)) evaluates to 3 days).


If you don't want a separate file, you could also store the last execution time in the modification time stamp of your script. That means however that making any changes to your script file will reset the 3 counter and be treated like if the script was successfully running.

To implement that, add the snippet below to the top of your script file:

#!/bin/bash

# Minimum delay between two script executions, in seconds. 
seconds=$((60*60*24*3))

# Compare the difference between this script's modification time stamp 
# and the current date with the given minimum delay in seconds. 
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test "$(($(date "+%s")-$(date -r "$0" "+%s")))" -lt "$seconds" ; then
    echo "This script may not yet be started again."
    exit 1
fi

# Store the current date as modification time stamp of this script file
touch -m -- "$0"

# Insert your normal script here:

Again, don't forget to adapt the value of seconds= to your needs ($((60*60*24*3)) evaluates to 3 days).

Related Question