重写了服务器备份shell脚本,并加入了main函数

3 min

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

大家好,我是无能。
我重写了之前写的一个用于创建备份的shell脚本。

前言

虽然是之前写的,但重新审视时,发现没有包含删除旧的tar.gz备份文件的代码,而且感觉会有点长,所以就将其整理到了main函数中。
对于我这种怕麻烦的人来说,尽可能地精简代码很重要,所以我重写了它。
实际上,如果能通过参数指定备份目的地和源,会更具通用性,并且在写入cron时也更容易理解,所以将来我会这样做。

代码解析

#!/bin/bash

MOUNT_DIR="/your/mount/point"

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

EXCLUDE_FILE=""  # 除外ファイル指定 --exclude=your/path
W_DIR=`echo $SRC_DIR | awk -F/ '{print $(NF)}'`

# マウントポイントを確認し、マウントされていなければマウントする
check_mount() {
    df | grep "$MOUNT_DIR" > /dev/null
    if [ $? -ne 0 ]; then
        break
    else
        mount $MOUNT_DIR || exit 1
    fi
}

# 古いバックアップファイルを削除する
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() {
    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  # マウントを確認し、必要ならマウント
    mkdir -p $MOUNT_DIR/$BK_DIR  # バックアップディレクトリの作成
    rm_old_backups  # 古いバックアップの削除
    create_backup  # 新しいバックアップの作成
    umount $MOUNT_DIR || exit 1  # マウント解除
}

main

由于假设会进行挂载/卸载操作,因此需要加入相应的判断。奇怪的是,虽然有mountpoint命令可以判断是否已挂载,但我尝试后发现即使已挂载也会显示“未挂载”,无法获取正确的返回值。
因此我突然想到,如果未挂载,它就不会出现在df的结果中。所以,如果我grep df的标准输出,并根据是否能grep到挂载点来判断返回值,应该会相当可靠吧……

最初,我只是简单地使用cp命令复制一次,然后用tar打包,但我想指定“复制时排除的文件”,而rsync似乎可以做到。原来大家都在用rsync啊。

特意指定$W_DIR的原因是rsync会用到它,所以需要提前创建这个值。
而关键在于删除旧tar.gz文件的判断逻辑。如果用ls来检查,就不必像find那样贪婪地深入到下层目录,我感觉这样对磁盘I/O的负载更小,也更安全,所以就尝试了这种方法。
通过tail获取文件名,可以明确决定允许保留多少个文件,我觉得这无意中是个不错的方法。

结束

说实话,我感觉也没必要非得放到main函数里,但结果是代码变得更易读了,所以就这么办吧。
那么,下次再见。

Related Posts