Cron/shell newbie

software development

#1

I’ve got a phpbb discussion board running OK and it seems wise to automate backups. I found a recommended shell script that keeps seven recent backups in rotation. Not being a programmer, I tried to delicately edit the variables I could identify to replace them with my own and surprisingly, it kinda-sorta works :slight_smile: What happens is I get a command not found error every time, but it does sucessfully make the backup. I’ve let it run eight days now, and I’ve got eight backups, so the pruning part also isn’t working. Here’s what I’ve done so far. If you can spot where I’ve gone wrong, pointers to the path of righteousness appreciated.

[code]#!/bin/sh

output_file="/home/user/domain/forum/backups/dump.sql"
count_files=ls -l /home/user/domain/forum/backups/db_name* | wc -l
count_files=expr $count_files - 1

if [ $count_files -gt 7 ]; then
file_list=ls -S -t -p -r /home/user/domain/forum/backups | grep gz
rm /home/user/domain/forum/backups/${file_list%%gz*}gz
fi

mysqldump -h forum.domain -u user --password=password db_name > $output_file 2>&1

filename="/home/user/domain/forum/backups/db_name_date +%Y-%m-%d.sql.gz"

gzip $output_file
mv $output_file.gz $filename

chmod g+wr /home/user/domain/forum/backups/*
[/code]This is in my home dir as db_rotate and is executable. If I go sh db_rotate I get an ‘Error: Command not found’ plus a successful backup in the directory where I expect it. The glass is half full!

(I’ve also tried using sh db_rotate >/dev/null in the crontab to avoid getting error-reporting mail every day, but I still get the email. Also, even if it worked, it would just be treating the symptom :slight_smile:

I tried pasting some of the standalone-type command lines at my shell prompt to see if I could discover the offending line that way, but the simpler ones all seemed to work. Some I don’t really know how to test.

I guess I’m happy that I’m at least getting some backups and don’t mind doing some of the pruning chores by hand, but I feel bad running such a sloppy process. I’d like to learn how to tidy this up. Thanks for any thoughts.


#2

I may be missing something, but I don’t see any glaring errors there. A couple things you might try:

  1. Try running the script one line at a time from the command line, replacing the variables with their values. Then see where you get that error.
  2. It’s generally a good idea to put the full path for commands, (ie /usr/bin/mysqldump rather than just ‘mysqldump’). Better yet, make them variables, ie:
    CHMOD=/bin/chmod
    (and later)
    $CHMOD 0777 file

Note that doing:
command >/dev/null

only redirects stdout and not stderr, so you’d still get that error if you ran the cron job… generally you want to dump stdout but not stderr with cron jobs (you can dump stderr too with command >/dev/null 2>&1).

As an aside, you don’t need to do ‘sh command’ - you can just make the script executable and call it from its full path (or ./ if you’re in the current directory).

So you might want to use something like:
MAILTO=you@example.com
30 3 * * * /home/user/bin/db_rotate > /dev/null


#3

Thank you Will. I will try all these ideas (one at a time :slight_smile: Cheers.


#4

Ah, I tried sh -x (echoes every line or output) and the problem seems to be in the neighborhood of the expr and -gt lines:

count_files=`ls -l /home/user/domain/forum/backups/db_name* | wc -l` count_files=expr $count_files - 1 gives the result:

count_files= 8 count_files=expr 8 - 1 db_rotate: 8: command not found '[ 8 -gt 7 ']' Contrary to my previous finger-counting, it did in fact delete the earliest backup and leave me with the seven lastest. I suspect a syntax problem somewhere in that counting procedure.


#5

Woohoo! More ticks and brackets did the trick. I’m a happy camper. Thanks Bob and Will.

Time for the next project. If I have a small site, is there a reason I couldn’t have a cron job make a tarball and mail to me once a week or month? I’ll scurry off now and start checking attachment size limits and reading the man pages for Mail :slight_smile:


#6

No reason you shouldn’t, but you will either need to uuencode the attachment prior to mailing it, or use a MIME aware tool to send the mail.

Something like this (untested) should work:
43 0 31 * * /usr/bin/mutt -F /dev/null -a backup.tar.gz -s "Backup for date" you@example.com

Our outgoing mail servers have a size limit of 40 Mb.


#7

Or you might have more luck creating a script and running this from cron at a periodic basis. A shell script would probably involve less overheads, but I know that Perl has excellent support for both TAR and MAIL, and I’m sure there are plenty of examples out there on websites such as http://www.hotscripts.com/.

  • wil

#8

Well the script was implied - the command I mentioned just mails the backup file to you – and that whole command line could easily be placed at the bottom of a shell / perl script.

A shell script would probably work fine. Note that you want to test the script and make sure that it doesn’t take up too much CPU for too long, or it might get killed.

A shell script would be perfectly adequate, but it’s really whatever you’re most comfortable in (ie the only reason to write it in perl is if you know perl well).

Something like this should work (untested)
#!/bin/sh

this assumes GNU tar

backup all files except for Maildir/ (add other patterns to --exclude as

needed, or use -X file and put a list of excluded patterns in this file

DATE=date "+%Y-%m-%d%n"

/usr/bin/tar czf $HOME/backup-$DATE.tar.gz --exclude=Maildir* $HOME

replace user@example.com with your email address obviously

/usr/bin/mutt -a $HOME/backup-$DATE.tar.gz -s “Backups for $DATE” -F /dev/null user@example.com


#9

I’m equally qualified to use perl or shell scripts (that is, not at all, for either :slight_smile:

I like the (apparent) linear simplicity of the shell script example. I tried the mutt line in a test script last night and got dropped into an interactive mode. I’ll fool around some more when I get home from work. I see a lot of mutt pages in a quick google.


#10

[quote]I tried the mutt line in a test script last night and got dropped into an interactive mode

[/quote]

My bad… you have to direct stdin from a file (or from /dev/null)… so just add:
< /dev/null to the end if you don’t want the message to have anything in the body (or you can take the body from a file instead of /dev/null).

or do:
echo “This is the body of the message” | mutt -a file -F /dev/null -s “Subject Here” you@example.com


#11

Hi,

Just thought I’d follow-up and say “Thanks!” I’ve received two different domain backups in the mail, and my SQL db’s are rotating like a roast on the rotisserie. Everything seems to be working. Your collective help is appreciated.
Cheers!