Problem running bash script in cron

I created a script in bash to be run in cron. When the script was executed manually, it would run just fine. But when I used cron to run it, it would not run. The script was for backup of certain files, and its major steps were:

  1. Tar the folder
  2. Put the folder on a Windows server using Samba

I found a post by ichbindev online (cron runs but script is not executed properly) about a similar problem but no solution. Searching Google revealed many, many users with the same problem. Since my aim was very similar to what ichbindev wanted to do, I took the liberty of emulating his code but changing it for my own requirements. His original code was:

#!/usr/bin/env bash
Date=`date "+%Y%m%d%H%M%S%n"`
DBUser="mydbuser"
UserPassword="mydbpassword"
BkpUser="mybkpuser"
BkpPassword="mybkppassword"
mysqldump mydatabase -u$DBUser -p$UserPassword > /home/me/daily-backup/mydatabase.sql
cd /home/me/daily-backup/
zip mydatabase-"$Date".zip mydatabase.sql
smbclient "//bkpserver/backup" -I10.10.1.10 -Wworkgroup -U $BkpUser%$BkpPassword < /home/me/scripts/smbclient-commands
rm mydatabase.sql mydatabase-"$Date".zip
cd /home/me/tempfiles/
rm -f *.csv

And I changed it (vim /home/me/scripts/dailybackup.sh) to look something like:

#!/bin/bash
Date=`date "+%Y%m%d%H%M%S%n"`
BkpUser="mybkpuser"
BkpPassword="mybkppassword"
tar cvzf /home/me/mybackups/dirone-"$Date".tar.gz /home/me/dirone/
tar cvzf /home/me/mybackups/dirtwo-"$Date".tar.gz /home/me/dirtwo/
cd /home/me/mybackups/
/usr/bin/smbclient "//bkpserver/backup" -I10.10.1.10 -Wworkgroup -U $BkpUser%$BkpPassword -c "prompt; mput *.tar.gz; quit;"
rm /home/me/mybackups/*.tar.gz

I made the file executable by user (chmod u+x /home/me/scripts/dailybackup.sh). I found that if I didn’t use cd /home/me/mybackups/ and instead used the complete path within the smbclient command (mput /home/me/mybackups/*.tar.gz), it wouldn’t transfer any files even when running the script manually. I also noticed that when using cron, the script would not put more than four files using smbclient (manually, it would put all files). Don’t ask me why.

Now my crontab file looked like his as well:

00 05 * * * /home/me/scripts/dailybackup.sh

But I had the same problem as him: cron would not run the script. It would create the tar file but not move it to the backup server. After doing lots of research, it turned out that cron has the default shell of sh. It can be determined by doing

less /etc/crontab

For some reason sh did not run smbclient while bash did. So I tried to change sh to bash in /etc/crontab and then restarting the cron service (sudo /etc/init.d/cron restart in Ubuntu) but it did not solve the problem. Lots more googling brought up a very useful page: HowTo: Using the cron shell tool to automate procedures – Part 2 of 3. It had one minor change to the crontab file, and now my crontab (crontab -e -u 'me') looked like:

SHELL=/bin/bash
00 05 * * * /home/me/scripts/dailybackup.sh

Notice that we set the SHELL variable within the crontab file so that instead of sh cron uses bash to run all scripts. This one change made all the difference and everything worked fine.

I think I should also look into the possibility of mounting the shared directory and then directly using it. I will post back when and if I try it and discover how it might work.

11 Responses to Problem running bash script in cron

  1. grig says:

    Thanks for the post! =)

  2. John says:

    Same problem … did everything except that last step of setting the SHELL in the crontab … will know tonight if it fixes my problem.

  3. Lobos says:

    Thanks – good to know!

    So, I’m sitting here wondering how this will fair in my case, as I have primarily korn shell scripts represented in my crontab on a Solaris 10 (SPARC) box… I’ve decided to do some testing –

    First, I am attempting to just add a crontab entry for the bash script to see if it will run or not.

    Well, /var/cron/log shows that the job ran as expected, and the desired steps in the script executed without failure. So, I am curious about which OS / platform / release this problem was experienced on. Of course, I haven’t ruled out the possibility that I have done something different in my script that prevents this from being an issue in my case…?

  4. hs says:

    @Lobos: this was done on Ubuntu Gutsy

  5. Stephen says:

    Thanks for the insight, that should fix my problems…

  6. jisse says:

    Thanks for this post, very helpfull

  7. Paul says:

    rather than change the shell crontab uses for everything you could just put “bash scriptname.bsh” in order to run that single script using the bash shell.

    and… thank for the info. it was helpful.

  8. Hari says:

    Thank you so much.. I tried it for one month..

  9. Ryan says:

    Dont forget if you just want to run a bash command from crontab add /bin/bash -c “command to run”

  10. ike says:

    Well, this is probably something like reviving a fossil taking the age of this thread into account, but anyway I came here too so probably someone can use this.

    There’s no need to modify the shell of your crontab to achieve this.
    You can just enter the cronjob as:

    /bin/bash scriptname

    then it will run scriptname with bash instead of sh.

  11. damitr says:

    Thanks helped me a lot.

    D