script backups sqlite database, when ran as a cron the db and names are mangled

I have a crontab:

 * * * * * /home/ipa/web/backup.sh > /dev/null 2>&1

(No it doesn't run every minute just testing here)

The backup.sh has this:

#!/usr/bin/env sh



sqlite3 /home/ipa/web/ipa_django/mysite/db.sqlite3 ".backup 'backup_file.sqlite3'"
src="/home/ipa/web/backup_file.sqlite3"
let seconds=$(date +%H)*3600+$(date +%M)*60+$(date +%S)
echo $seconds
filename="db.sqlite3"
echo $filename.$seconds
dest="/home/ipa/web/db_backups/"$filename.$seconds
cp  $src $dest
cd /home/ipa/web/db_backups
tar -cvzf ipadbbackup.tar.gz $filename.$seconds
cd /home/ipa/web/
cp /home/ipa/web/db_backups/ipadbbackup.tar.gz ipadbbackup.tar.gz
rm /home/ipa/web/db_backups/$filename.$seconds
rm /home/ipa/web/db_backups/ipadbbackup.tar.gz
#rm "$srcfile"
/usr/bin/bash start-app.sh;
echo "Running email backup"
python2.7 backup_via_email.py
rm ipadbbackup.tar.gz

The idea is I copy the database to a scratch area, zip it up copy it to where another .py file can find it and email it off as a backup.

The problem is:

If I run this script from where it lives: /home/ipa/web/

with a ./backup.sh

It works great, I get the file in my email works great: db.sqlite3.77627

or what not... the problem is when it runs as a cron the file is not complete and the file name is:

db.sqlite3.

I cannot figure out what about it running as a cron is making it fail essentially? The file in the tar is also 2.1k smaller? So not sure what is going on... not even sure where to look.


Solution 1:

Most likely, you're not actually running ./backup.sh when running it manually but rather bash ./backup.sh.

The only POSIX compliant way to compute a value through the shell is with $(( expr )).

In general, unless you have very good reason, scripts should use bash since most people don't know the difference between sh and bash and will just write broken scripts.

#!/usr/bin/env bash

set -e
set -u

declare -r db_src="/home/ipa/web/ipa_django/mysite/db.sqlite3"
declare -r db_bak="/home/ipa/web/backup_file.sqlite3"
declare -r db_dst="/home/ipa/web/db_backups/db.sqlite3.$[ EPOCHSECONDS % 86400 ]"
 
sqlite3 "${db_src}" ".backup 'backup_file.sqlite3'"
cp "${db_bak}" "${db_dst}"
cd "$( dirname "${db_dst}" )"
tar -czf "/home/ipa/web/ipadbbackup.tar.gz" "$( basename "${db_dst}" )"
rm "${db_dst}"

echo "Running email backup"
cd "/home/ipa/web" 
python2.7 backup_via_email.py
rm ipadbbackup.tar.gz

Always make sure to log your cron output when attempting to debug, I'm guessing you'd have seen a command not found: let somewhere.