Re: Help with script - doesn't work properly from cron
On Fri, Jul 17, 2009 at 02:53:21PM -0700, Erik Olof Wahlstrom wrote: #!/bin/bash BACKUP_DIR=/media/disk/AUTOMATED_BACKUPS/DB_DAILY CURRENT_DIR=$BACKUP_DIR/`date +%d` # See how you call date here without an explicit path? That's good. DATABASES=$(/usr/bin/mysql -uUsername -pPassword -Bse 'show databases') echo 'Backing up databases: '$DATABASES echo Backing up databases: $DATABASES if [ -e $CURRENT_DIR ] if [ -d $CURRENT_DIR ] # Of course, if it's a file, you would have problems below then cd $CURRENT_DIR /bin/rm * cd $CURRENT_DIR || exit 1 rm -f * # NEVER do rm * after a cd without checking that the cd # succeeded! # You don't need an explicit path on rm. You didn't need one # on date, so why put one on rm? # In this particular version of this particular script, you can # get away with not quoting the $CURRENT_DIR parameter expansion, # but quoting it will save your butt if someone changes it, e.g.: # CURRENT_DIR='/media/disk/c/Program Files' else /bin/mkdir $CURRENT_DIR mkdir -p $CURRENT_DIR cd $CURRENT_DIR cd $CURRENT_DIR || exit 1 fi for DB in $DATABASES do /usr/bin/mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $DB_`date +%Y-%m-%d_%k.%M`.sql.bz2 # Long line, probably broken by your mailer. For clarity, I'd # write it on two lines explicitily: mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%k.%M).sql.bz2 done exit 0 Can any skilled eyes see why this doesn't work when it is run from the roots crontab? None of the changes I suggested should really affect that. Perhaps it's some sort of mysql-specific thing? Additionally, when I run the script as root in the terminal, I get the following output: Backing up databases: information_schema db1 db2 db3 /bin/rm: cannot remove `*': No such file or directory The rm -f will suppress that error message. Is there a better way to clear out last months files before making the current backups? You could also consider writing it this way: cd / rm -rf $CURRENT_DIR mkdir -p $CURRENT_DIR cd $CURRENT_DIR || exit 1 Then you don't even need to check whether it already exists. On Sat, Jul 18, 2009 at 11:25:13AM +0200, Bernd Eggink wrote: You could replace the whole if-then-else clause by mkdir -p $CURRENT_DIR cd $CURRENT_DIR rm -f * Another failure to check the results of cd before doing rm *. This can and will lead to disasters.
Re: Help with script - doesn't work properly from cron
Greg Wooledge wrote: Erik Olof Wahlstrom wrote: /usr/bin/mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $DB_`date +%Y-%m-%d_%k.%M`.sql.bz2 # Long line, probably broken by your mailer. For clarity, I'd # write it on two lines explicitily: mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%k.%M).sql.bz2 You might want to set umask restrictive so that the backup file created by the redirection isn't world readable. umask 077 I have never liked whitespace in filenames and %k may produce spaces in filenames. Better IMNHO to use %H here and avoid the space. Why use a dot instead of the more common colon in the time? mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%H:%M).sql.bz2 You could also consider writing it this way: cd / rm -rf $CURRENT_DIR mkdir -p $CURRENT_DIR cd $CURRENT_DIR || exit 1 Then you don't even need to check whether it already exists. Why bother changing directory there at all? :-) mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $CURRENT_DIR/${DB}_$(date +%Y-%m-%d_%H:%M).sql.bz2 Bernd Eggink wrote: You could replace the whole if-then-else clause by mkdir -p $CURRENT_DIR cd $CURRENT_DIR rm -f * Another failure to check the results of cd before doing rm *. This can and will lead to disasters. Doing 'rm *' just makes me extremely nervous even when care is taken to ensure that it is going to work okay. I think it is safer to avoid it. Let me suggest the following: CURRENT_DIR=$BACKUP_DIR/`date +%d` ... cd $CURRENT_DIR || exit 1 ... mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%k.%M).sql.bz2 In this case the file name is going to be SOMETHING.sql.bz2. Instead of using 'rm *' it would make me much less nervous to qualify that file glob with 'rm -f *.sql.bz2' at least so that if this were to escape and be invoked elsewhere it would have limited damage potential. cd $CURRENT_DIR || exit 1 rm -f *.sql.bz2 Is there a better way to clear out last months files before making the current backups? Personally I have the following line in my /etc/cron.d/local-mysql crontab. The 'savelog' command with -c7 will save seven days of datestamped backups (sufficient for my case) without further code. That could easily be -c30 to save 30 days worth. The 'savelog' command pretty much handles all of your issues with datestamping and cycling files very easily. 30 3 * * * root umask 077 ; mysqldump --defaults-file=/etc/mysql/debian.cnf --all-databases | gzip /var/backups/mysql.dump ; savelog -q -d -l -C -c7 /var/backups/mysql.dump Bob
Re: Help with script - doesn't work properly from cron
Thanks everyone for your pointers - I ended up with this: #!/bin/bash BACKUP_DIR=/media/disk/AUTOMATED_BACKUPS/DB_DAILY CURRENT_DIR=$BACKUP_DIR/`date +%d` DATABASES=$(mysql -uroot -pNewSecretPw -Bse 'show databases') echo 'Backing up databases: '$DATABASES cd / rm -rf $CURRENT_DIR mkdir -p $CURRENT_DIR cd $CURRENT_DIR || exit 1 for DB in $DATABASES do mysqldump -uroot -pNewSecretPw $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%H:%M).sql.bz2 done exit 0 It worked on the first manual run - keeping my fingers crossed for tonight! :-P Bob Proulx wrote: Greg Wooledge wrote: Erik Olof Wahlstrom wrote: /usr/bin/mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $DB_`date +%Y-%m-%d_%k.%M`.sql.bz2 # Long line, probably broken by your mailer. For clarity, I'd # write it on two lines explicitily: mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%k.%M).sql.bz2 You might want to set umask restrictive so that the backup file created by the redirection isn't world readable. umask 077 I have never liked whitespace in filenames and %k may produce spaces in filenames. Better IMNHO to use %H here and avoid the space. Why use a dot instead of the more common colon in the time? mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%H:%M).sql.bz2 You could also consider writing it this way: cd / rm -rf $CURRENT_DIR mkdir -p $CURRENT_DIR cd $CURRENT_DIR || exit 1 Then you don't even need to check whether it already exists. Why bother changing directory there at all? :-) mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $CURRENT_DIR/${DB}_$(date +%Y-%m-%d_%H:%M).sql.bz2 Bernd Eggink wrote: You could replace the whole if-then-else clause by mkdir -p $CURRENT_DIR cd $CURRENT_DIR rm -f * Another failure to check the results of cd before doing rm *. This can and will lead to disasters. Doing 'rm *' just makes me extremely nervous even when care is taken to ensure that it is going to work okay. I think it is safer to avoid it. Let me suggest the following: CURRENT_DIR=$BACKUP_DIR/`date +%d` ... cd $CURRENT_DIR || exit 1 ... mysqldump -uroot -pHardAsMySql321 $DB | bzip2 ${DB}_$(date +%Y-%m-%d_%k.%M).sql.bz2 In this case the file name is going to be SOMETHING.sql.bz2. Instead of using 'rm *' it would make me much less nervous to qualify that file glob with 'rm -f *.sql.bz2' at least so that if this were to escape and be invoked elsewhere it would have limited damage potential. cd $CURRENT_DIR || exit 1 rm -f *.sql.bz2 Is there a better way to clear out last months files before making the current backups? Personally I have the following line in my /etc/cron.d/local-mysql crontab. The 'savelog' command with -c7 will save seven days of datestamped backups (sufficient for my case) without further code. That could easily be -c30 to save 30 days worth. The 'savelog' command pretty much handles all of your issues with datestamping and cycling files very easily. 30 3 * * * root umask 077 ; mysqldump --defaults-file=/etc/mysql/debian.cnf --all-databases | gzip /var/backups/mysql.dump ; savelog -q -d -l -C -c7 /var/backups/mysql.dump Bob -- View this message in context: http://www.nabble.com/Help-with-script---doesn%27t-work-properly-from-cron-tp24542164p24579084.html Sent from the Gnu - Bash mailing list archive at Nabble.com.
Re: Help with script - doesn't work properly from cron
Erik Olof Wahlstrom schrieb: Hello - I am having a problem with a backup script that I have put together - when I run it as root from the terminal, it works as expected (with one caveat); however, when cron runs it, the daily backup folder is created but no files are deposited into that folder... Here is the script: #!/bin/bash BACKUP_DIR=/media/disk/AUTOMATED_BACKUPS/DB_DAILY CURRENT_DIR=$BACKUP_DIR/`date +%d` DATABASES=$(/usr/bin/mysql -uUsername -pPassword -Bse 'show databases') echo 'Backing up databases: '$DATABASES if [ -e $CURRENT_DIR ] then cd $CURRENT_DIR /bin/rm * else /bin/mkdir $CURRENT_DIR cd $CURRENT_DIR fi for DB in $DATABASES do /usr/bin/mysqldump -uroot -pHardAsMySql321 $DB | bzip2 $DB_`date +%Y-%m-%d_%k.%M`.sql.bz2 done exit 0 Can any skilled eyes see why this doesn't work when it is run from the roots crontab? The reason may be that crontab commands are run with /bin/sh -c command (Bourne shell mode). Try changing the crontab entry to /bin/bash command. Additionally, when I run the script as root in the terminal, I get the following output: Backing up databases: information_schema db1 db2 db3 /bin/rm: cannot remove `*': No such file or directory Is there a better way to clear out last months files before making the current backups? You could replace the whole if-then-else clause by mkdir -p $CURRENT_DIR cd $CURRENT_DIR rm -f * provided the options are supported on your system. Regards, Bernd -- Bernd Eggink http://sudrala.de