【概要】
rsyncで世代バックアップを取得するスクリプトです。
シェルスクリプト(bash)で、
CRONに登録することを想定しています。
手動実行も可能です。
※スクリプトを使用する場合は、充分にテストしてからご利用ください
バックアップ元からバックアップ先にrsyncします。
バックアップ元または、バックアップ先をリモート(SSH接続)とすることもできます。
※バックアップ先と、バックアップ元の両方をリモートにすることはできません。
バックアップ先で世代管理を行います。
世代管理処理の流れとしては下記になります。(2022年4月に処理を更新しました)
◆3世代の例
1回目:バックアップ先に世代1ディレクトリを作成してrsync
2回目:バックアップ先に世代2ディレクトリを作成してrsync
3回目:バックアップ先に世代3ディレクトリを作成してrsync
4回目:バックアップ先の世代1ディレクトリを新規の世代3にリネームしてrsync
※リネームはrsyncの負荷を減らすことを目的にしています。
リネームするため、一時的に1世代減るのでご注意ください。
バックアップ先をリモートにする場合は、スクリプトの関数をSSHコマンド経由で渡して実行します。
(typeset -f)
【動作確認した環境】
Centos7.9
【前提条件】
・SSHを使用する場合はSSH公開鍵認証でバックアップ元にパスワードなしで接続可能なこと
(下記の【その他】参照)
・SSHを使用する場合は接続元と接続先の両方にrsyncがインストールされていること
(下記の【その他】参照)
【rsyncgen.sh】
#!/bin/bash
### Set rsync directory and generation #########################################
# Caution: source and destination cannot both be remote.
## rsync source directory
# / is not required at the end of the directory
# (exsample: DIR_SRC=/root/testsrcdir)
# (example: DIR_SRC_USER="testuser", if not use : DIR_SRC_USER="")
# (example: DIR_SRC_IP="192.168.1.10" , if not use : DIR_SRC_IP="")
DIR_SRC=<バックアップ元ディレクトリフルパス>
DIR_SRC_USER=""
DIR_SRC_IP=""
## rsync destination directory
# / is not required at the end of the directory
# (exsample: DIR_SRC=/root/testdstdir)
# (example: DIR_DST_USER="testuser", if not use : DIR_DST_USER="")
# (example: DIR_DST_IP="192.168.1.10" , if not use : DIR_DST_IP="")
DIR_DST=<バックアップ先ディレクトリフルパス>
DIR_DST_USER=""
DIR_DST_IP=""
## backup generation
# (exsample: BKUP_GEN_FULL=3)
BKUP_GEN_FULL=<数字>
################################################################################
# variable initialization
RC=0
DIR_DST_SSH_FLG=0
DIR_SRC_SSH=""
DIR_DST_SSH=""
YYYYMMDD_hhmmss=$(date '+%Y%m%d_%H%M%S')
# backup generation check
echo "${BKUP_GEN_FULL}" | grep -q "^[0-9]\+$"
RC=$?
if [ "${RC}" != "0" ] || [ ${BKUP_GEN_FULL} -le 0 ] ; then
/usr/bin/logger "ERROR: rsync script NUM_SRC variable error: ${BKUP_GEN_FULL}"
exit 1
fi
# rsync directory check
if [ -z "${DIR_SRC}" ] || [ "${DIR_SRC}" = "/" ] ; then
/usr/bin/logger "ERROR: rsync script DIR_SRC variable error: ${DIR_SRC}"
exit 1
fi
if [ -n "${DIR_SRC_USER}" ] && [ -n "${DIR_SRC_IP}" ] ; then
DIR_SRC_SSH="${DIR_SRC_USER}@${DIR_SRC_IP}:${DIR_SRC}"
else
DIR_SRC_SSH="${DIR_SRC}"
fi
if [ -n "${DIR_DST_USER}" ] && [ -n "${DIR_DST_IP}" ] ; then
DIR_DST_SSH="${DIR_DST_USER}@${DIR_DST_IP}:${DIR_DST}"
DIR_DST_SSH_FLG=1
else
DIR_DST_SSH="${DIR_DST}"
fi
# DIR_DST generation management
function dst_gen_mng () {
# variable initialization
NUM_DST_FULL=0
NUM_DEL_FULL=0
FNC_RC=0
FNC_DIR_DST=$1
FNC_BKUP_GEN_FULL=$2
FNC_YYYYMMDD_hhmmss=$3
# rsync directory check
if [ -z "${FNC_DIR_DST}" ] || [ "${FNC_DIR_DST}" = "/" ] ; then
/usr/bin/logger "ERROR: rsync script FNC_DIR_DST variable error: ${FNC_DIR_DST}"
exit 1
fi
ls -1 ${FNC_DIR_DST} | grep "^BKUP_GEN_FULL_" > /dev/null 2>&1
FNC_RC=$?
if [ "${FNC_RC}" = "0" ] ; then
cd ${FNC_DIR_DST}
NUM_DST_FULL=$(ls -1d ${FNC_DIR_DST}/BKUP_GEN_FULL_* | sort -r | wc -l)
if [ ${NUM_DST_FULL} -gt 0 ] ; then
# delete over 1 more generation
if [ ${NUM_DST_FULL} -gt ${FNC_BKUP_GEN_FULL} ] ; then
NUM_DEL_FULL=$(expr ${NUM_DST_FULL} - ${FNC_BKUP_GEN_FULL})
ls -1d ${FNC_DIR_DST}/BKUP_GEN_FULL_* | sort -r | tail -n ${NUM_DEL_FULL} | xargs rm -rf
FNC_RC=$?
if [ "${FNC_RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script rm command return code: ${FNC_RC}"
exit 1
fi
fi
# rename over oldest generation(reduce rsync diff)
if [ ${NUM_DST_FULL} -ge ${FNC_BKUP_GEN_FULL} ] ; then
NUM_DEL_FULL=$(expr ${NUM_DST_FULL} - ${FNC_BKUP_GEN_FULL})
LAST_GEN_FULL=$(ls -1d ${FNC_DIR_DST}/BKUP_GEN_FULL_* | sort -r | tail -1)
mv ${LAST_GEN_FULL} ${FNC_DIR_DST}/BKUP_GEN_FULL_${FNC_YYYYMMDD_hhmmss}
FNC_RC=$?
if [ "${FNC_RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script mv command return code: ${FNC_RC}"
exit 1
fi
else
# mkdir backup direcotry
if [ ! -d ${FNC_DIR_DST}/BKUP_GEN_FULL_${FNC_YYYYMMDD_hhmmss} ] ; then
mkdir -p ${FNC_DIR_DST}/BKUP_GEN_FULL_${FNC_YYYYMMDD_hhmmss}
FNC_RC=$?
if [ "${FNC_RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script mkdir: ${FNC_DIR_DST}"
exit 1
fi
fi
fi
fi
else
# mkdir backup direcotry
if [ ! -d ${FNC_DIR_DST}/BKUP_GEN_FULL_${FNC_YYYYMMDD_hhmmss} ] ; then
mkdir -p ${FNC_DIR_DST}/BKUP_GEN_FULL_${FNC_YYYYMMDD_hhmmss}
FNC_RC=$?
if [ "${FNC_RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script mkdir: ${FNC_DIR_DST}"
exit 1
fi
fi
fi
}
# run funciton dst_gen_mng
if [ "${DIR_DST_SSH_FLG}" = "1" ] ; then
ssh ${DIR_DST_USER}@${DIR_DST_IP} "$(typeset -f dst_gen_mng); dst_gen_mng ${DIR_DST} ${BKUP_GEN_FULL} ${YYYYMMDD_hhmmss}"
RC=$?
if [ "${RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script function dst_gen_mng: ssh run"
exit 1
fi
else
dst_gen_mng ${DIR_DST} ${BKUP_GEN_FULL} ${YYYYMMDD_hhmmss}
RC=$?
if [ "${RC}" != "0" ] ; then
/usr/bin/logger "ERROR: rsync script function dst_gen_mng: local run"
exit 1
fi
fi
# run rsync
/usr/bin/rsync -ar --delete ${DIR_SRC_SSH} ${DIR_DST_SSH}/BKUP_GEN_FULL_${YYYYMMDD_hhmmss}
RC=$?
# return code check and logging
if [ "${RC}" = "0" ] ; then
/usr/bin/logger "INFO: rsync script success ${DIR_SRC_SSH} ${DIR_DST_SSH}"
else
/usr/bin/logger "ERROR: rsync script rsync failed. ${DIR_SRC_SSH} ${DIR_DST_SSH} return code: ${RC}"
exit 1
fi
exit 0
【使用方法】
①viでシェルスクリプト作成
viエディタでファイルを新規作成して、上記「rsyncgen.sh」の内容を貼り付けます。
$ vi rsyncgen.sh
下記を環境にあわせて編集し、保存します。SSH経由の場合は、「DIR_SRC_USER、DIR_SRC_IP」または「DIR_DST_USER、DIR_DST_IP」も編集してください。※両方ともリモートにすることはできません
・DIR_SRC=<バックアップ元ディレクトリ>
・DIR_DST=<バックアップ先ディレクトリ>
・BKUP_GEN=<数字>
②パーミッションを変更
$ chmod 700 rsyncgen.sh
③スクリプトを実行して動作確認
詳細な動作確認をする場合
「/usr/bin/bash -x rsyncgen.sh」で実行できます。
スクリプト実行前に、スクリプトを動作確認用に編集すると安全です。
rsyncはオプションが多数ありますので、必要に応じてスクリプト処理を変更ください。
「/usr/bin/rsync -a --delete ${SRC} ${DST}
」
→「/usr/bin/rsync -ahvn --delete ${SRC} ${DST}
」など。
(-nはDRY RUNで実際には実行せず動作確認できます)
通常実行は下記です。
$ ./rsyncgen.sh
負荷に応じて、「nice」コマンドや「ionice」コマンドの利用もご検討ください。
④CRON登録
「crontab -l」で確認、「crontab -e」で編集します。編集時の操作方法はviのエディタと同じです。
「<分> <時> <日> <月> <曜日> <シェルスクリプトのフルパス> > /dev/null 2>&1」
例)
45 22 * * * /root/backup/rsyncgen.sh > /dev/null 2>&1
【注意点】
※rsyncはフルバックアップを使用しています。
※バックアップはバックアップ先ディレクトリ配下の「BKUP_GEN_FULL_YYYYMMDD_hhmmss」(YYYYMMDD_hhmmssは日時)に格納されます
※loggerコマンドで/var/log/messageにログを出力しています
【その他】
◆rsyncのインストール
Centosに新規インストールの場合、rootユーザにて「yum install rsync」コマンドで可能です。
◆SSH公開鍵接続の設定例
・接続元
①接続用ユーザでログインまたは「su <ユーザ名>」コマンドでスイッチ
②ユーザのホームディレクトリへ移動
$ cd
③鍵確認
(「id_rsa」、「id_rsa.pub」ファイルが無いこと。ある場合は⑤へ)
(「.ssh」ディレクトリがない場合はコマンド「mkdir .ssh」→「chmod 700 .ssh」)
$ ls -l .ssh
④鍵作成
(確認事項は格納ディレクトリとパスワード。全部Enterキー押下でもOKです)
$ ssh-keygen -t rsa
⑤公開鍵id_rsa.pubの内容を表示
(メモ帳等にコピペして記録)
$ cat .ssh/id_rsa.pub
⑥鍵ファイルのパーミッションを変更
$ chmod 600 .ssh/id_rsa
$ chmod 600 .ssh/id_rsa.pub
・接続先
①接続許可ユーザでログインまたはsuでスイッチ
②ユーザのホームディレクトリへ移動
$ cd
③鍵確認
(「.ssh」ディレクトリがない場合はコマンド「mkdir .ssh」→「chmod 700 .ssh」)
$ ls -l .ssh
④鍵接続許可ファイル作成
(「authorized_keys」ファイルに公開鍵id_rsa.pubの内容を記載。既存で内容がある場合は追記)
$ vi .ssh/authorized_keys
⑤鍵接続許可ファイルのパーミッションを変更
$ chmod 600 .ssh/authorized_keys
・接続元
①接続用ユーザでログインまたは「su <ユーザ名>」コマンドでスイッチ
②SSH接続
(初回接続時はknown_hostsファイルに登録するフィンガープリントを確認されるので
「yes」を入力してEnterキー)
$ ssh <接続先ユーザ>@<接続先IPアドレス>