bashshellcron

Looking for input on a linux command line expression to evaluate date and if condition is met execute script


Looking to add a crontab entry to run a job every three days from the date of first execution.

I have the arithmetic evaluation working.

echo $((($(date +%s) - $(date -d "2024-12-22" +%s)) / 86400 % 3 == 0))

Updating the command to attempt script execution returns "bash: line 1: 0: command not found"

bash -c '$((($(date +%s) - $(date -d "2024-12-22" +%s)) / 86400 % 2 == 0)) && /scripts/backup/db_bak.sh'

I assume this is a case of not having the correct syntax, most likely related to the parenthesis or lack of brackets? I plugged the above line into shellcheck.net and it returned "No issues detected!" so perhaps a bit more nuanced than simple syntax.


Solution

  • You're trying to use an arithmetic context for a conditional. You can't use the arithmetic expansion $((...)) for that; the expansion is evaluated, and then Bash tries to run the result as a command. For example:

    $ echo $((1 + 1 > 2))
    0
    

    since 1 + 1 > 2 is not true.

    If you use that directly as a conditional, like

    $((1 + 1 > 2)) && echo "The condition is true"
    

    it is expanded to

    0 && echo "The condition is true"
    

    and then Bash complains that 0 isn't a command. (And it would complain that 1 isn't a command for a true condition.)

    What you have to do instead: use the ((...)) conditional construct. If the value of the expression is non-zero, it is considered true, which is what we want:

    ((1 + 1 > 2)) && echo "The condition is true"
    

    won't print anything, and

    ((1 + 1 == 2)) && echo "The condition is true"
    

    prints The condition is true.


    tl;dr: you have to drop the leading $ from your command.

    bash -c '((($(date +%s) - $(date -d "2024-12-22" +%s)) / 86400 % 2 == 0)) && /scripts/backup/db_bak.sh'
    

    Notice that if you run this exact command as a cronjob, you also have to escape the %, or they might be considered newlines (see crontab manual). Annoyingly, the backslash to escape is still passed through to the shell, so Bash will be confused about the invalid \% operator.

    A solution to that is moving the logic that contains the % into the script itself, so you don't have to worry about escaping.