Rewrote server backup shell script by adding a main function

5 min

language: ja bn en es hi pt ru zh-cn zh-tw

Hello, I'm Munou.
I rewrote the shell script for creating backups that I wrote a while ago.

Introduction

I wrote this a while ago, but looking at it again, I realized I hadn't included code to delete old backed-up tar.gz files, and it seemed like it was going to get a bit long, so I refactored it into a main function.
For a lazy person like me, it's important to keep things as short as possible, so I tried rewriting it.
Ideally, I'd make it more versatile by allowing the backup destination and source to be specified as arguments, which would also make it clearer when written in cron, so I'll do that eventually.

Dissection

#!/bin/bash

MOUNT_DIR="/your/mount/point"

SRC_DIR="/want/to/backup/dir"
BK_DIR="backupdir"

EXCLUDE_FILE=""  # Specify exclude file --exclude=your/path
W_DIR=`echo $SRC_DIR | awk -F/ '{print $(NF)}'`

# Check mount point, and mount if not mounted
check_mount() {
    df | grep "$MOUNT_DIR" > /dev/null
    if [ $? -ne 0 ]; then
        break
    else
        mount $MOUNT_DIR || exit 1
    fi
}

# Delete old backup files
rm_old_backups() {
    BK_COUNT=`ls -1 $MOUNT_DIR/$BK_DIR/*.tar.gz 2>/dev/null | wc -l`
    if [ "$BK_COUNT" -ge 3 ]; then
        ls -1t $MOUNT_DIR/$BK_DIR/*.tar.gz | tail -n +4 | while read file; do
            rm -f "$file"
        done
    fi
}

# Create backup
create_backup() {
    rsync -av $EXCLUDE_FILE $SRC_DIR $MOUNT_DIR/$BK_DIR
    tar cfz $MOUNT_DIR/$BK_DIR/"$W_DIR"_`date +"%Y%m%d"`.tar.gz -C $MOUNT_DIR/$BK_DIR $W_DIR
    rm -rf $MOUNT_DIR/$BK_DIR/$W_DIR/*
}

main() {
    check_mount  # Check mount, mount if necessary
    mkdir -p $MOUNT_DIR/$BK_DIR  # Create backup directory
    rm_old_backups  # Delete old backups
    create_backup  # Create new backup
    umount $MOUNT_DIR || exit 1  # Unmount
}

main

Since I'm assuming mounting/unmounting, I needed to include that check. It's strange, but there's a mountpoint command that can determine if something is mounted, but when I tried it, it sometimes showed 'not mounted' even when it was, and I couldn't get a proper return value.
So, I thought, if it's not mounted, it won't appear in the df output. Therefore, checking the return value after grepping the df standard output for the mount point should be quite reliable, I guess...

Originally, I simply copied with the cp command and then compressed with tar, but I wanted to specify "exclude files for copying", and it seems rsync can do that. That's why everyone is starting to use rsync.

The reason I explicitly specified $W_DIR was that I needed to create the value for use with rsync.
The key part is the logic for deleting old tar.gz files. I tried it because I felt that checking with ls instead of greedily looking into subdirectories with find would put less load on disk I/O and be safer.
And by getting the filenames with tail, I can clearly decide how many files to allow, which I think is quite good.

Conclusion

Well, honestly, I don't think it was strictly necessary to put it into a main function, but I feel it ended up being more readable, so I'll consider it a success.
That's all for now. Until next time.

Related Posts