2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【bash】bashシェルスクリプトでログのバックアップ【Linux】

Last updated at Posted at 2024-04-06

はじめに

bashシェルスクリプトの勉強がてらに、実環境でも使えそうなスクリプトの作成をしてみようと思い、今回のログバックアップスクリプトの作成を行いました。

まだ実務4カ月程の為お手柔らかにお願いします。

スクリプトの要件

  • バックアップ先ディレクトリは自動作成
  • ログローテートされた前日日付のログをバックアップ
  • gzip形式で圧縮
  • 圧縮前の生データはそのまま残す
  • backupディレクトリ内で各ログのディレクトリを振り分ける
  • backupディレクトリは/tmp/配下に(テストなんで適当に)
  • 7日以上前のバックアップは削除する
  • 各処理をログに出力
  • ログにはタイムスタンプを付ける
  • 削除したログは","区切りで分かりやすく表示
  • 失敗処理には [error] タグをつける
  • コマンドの標準エラー出力はログに出力
  • バックアップ対象はリスト化しループ処理させる

ざっくり以上の要件で作成を行いました。

スクリプト本文

#!/bin/bash

yesterday=`date -d "1 days ago" "+%Y%m%d"`
backup_log="/var/log/backup.log"

list=(
	"/var/log/messages"
	"/var/log/cron"
)

for i in ${list[@]}
do
	# listから第4フィールドを抜き出し変数へ格納
	log_name=`echo "${i}" | awk -F '/' '{print $4}'`
	# バックアップ対象のファイル名
	log="${i}"-"${yesterday}"
	# 圧縮後のログファイル名
	commpress_log="${log}.gz"
	# バックアップの転送先ディレクトリ
	to_dir="/tmp/backup/${log_name}/"


	# バックアップ転送先ディレクトリが存在しなければ作成
	if [[ ! -d "${to_dir}" ]]; then		
		mkdir -p "${to_dir}" 2>> "${backup_log}"
	fi

	# 処理開始
	echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] ログバックアップを開始します" > /dev/null >> "${backup_log}"
	
	# バックアップ対象の存在確認、存在していればバックアップ処理
	if [[ -f "${log}" ]];then		
		gzip -fk "${log}" 2>> "${backup_log}"
		rc1=$?
		mv "${commpress_log}" "${to_dir}" 2>> "${backup_log}"
		rc2=$?
		# 圧縮、転送が完了していれば成功
		if [[ "${rc1}" == 0 && "${rc2}" == 0 ]]; then			
			echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] "${log}"のバックアップが成功しました" > /dev/null >> "${backup_log}"
		else
			echo "`date "+%Y/%m/%d %H:%M:%S"`: [error] "${log}"のバックアップが失敗しました" > /dev/null >> "${backup_log}"		
		fi	
	else
		echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] バックアップ対象のログが存在しませんでした" > /dev/null >> "${backup_log}"
	fi


	# 保管期間の過ぎたバックアップの削除処理を開始
	echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] 保存期間切れの "${log_name}" の削除を開始します"  > /dev/null >> "${backup_log}"	
	# 7日以上の前のバックアップが存在すれば変数に格納
	searchlog=`find "${to_dir}" -type f -mtime +6 -name ""${log_name}"-*"`
	# 保管期間切れのバックアップのファイル名だけを抽出、複数あれば","区切りで表示
	rmlog=`echo "${searchlog}" | awk -F '/' '{print $5}' | sed -z 's/\n/,/g'`
	
	# 7日以上の前のバックアップが存在すれば削除
	if [[ ! -z "${searchlog}" ]]; then
	    echo "${searchlog}" | xargs rm -f 2>> "${backup_log}"
		rc3=$?
		if [[ "${rc3}" == 0 ]]; then
	    echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] 削除ファイル: "${rmlog}""  > /dev/null >> "${backup_log}"
		echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] 保管期間切れ "${log_name}" の削除が成功しました "  > /dev/null >> "${backup_log}"	
		else
			echo "`date "+%Y/%m/%d %H:%M:%S"`: [error] 保管期間切れ "${log_name}" の削除が失敗しました "  > /dev/null >> "${backup_log}"
		fi
	else
	echo "`date "+%Y/%m/%d %H:%M:%S"`: [info] 保存期間切れの "${log_name}" は存在しませんでした"  > /dev/null >> "${backup_log}"
	fi
done

実行してみた

前提

  • スクリプトファイル名"test.sh"
  • 格納先/home/test/

バックアップ対象となるログを1日前の日付で適当に作成します。
今回はmessagesとcronを対象にします。

$ touch -t "202404050000" /var/log/messages-20240405
$ touch -t "202404050000" /var/log/cron-20240405

ではスクリプトを実行してみます。

$ /home/test/test.sh
$ pwd
/tmp/backup
$ ll
合計 0
drwxr-xr-x. 2 root root 30  4月  6 20:30 cron
drwxr-xr-x. 2 root root 34  4月  6 20:30 messages

/tmp/backupは以下に

  • corn
  • messages
    ディレクトリが作成されています。
    それぞれ中を確認してみます。
$ pwd
/tmp/backup/cron
$ ll
合計 4
-rw-r--r--. 1 root root 34  4月  5 00:00 cron-20240405.gz

$ pwd
/tmp/backup/messages
$ ll
合計 4
-rw-r--r--. 1 root root 38  4月  5 00:00 messages-20240405.gz

無事バックアップ成功しているようですね。

では、ログの出力を確認してみます。

# cat /var/log/backup.log
2024/04/06 20:30:37: [info] ログバックアップを開始します
2024/04/06 20:30:37: [info] /var/log/messages-20240405のバックアップが成功しました
2024/04/06 20:30:37: [info] 保存期間切れの messages の削除を開始します
2024/04/06 20:30:37: [info] 保存期間切れの messages は存在しませんでした
2024/04/06 20:30:37: [info] ログバックアップを開始します
2024/04/06 20:30:37: [info] /var/log/cron-20240405のバックアップが成功しました
2024/04/06 20:30:37: [info] 保存期間切れの cron の削除を開始します
2024/04/06 20:30:37: [info] 保存期間切れの cron は存在しませんでした

このようにログも問題なく出力されていますが。
続いては、削除対象のログを適当に作成します。
複数対象が欲しいのでそれぞれ2ファイルずつ7日以上前の日付で作成します。

$ touch -t "202403010000" /tmp/backup/messages/messages-202403
01.gz
$ touch -t "202403020000" /tmp/backup/messages/messages-202403
02.gz
$ touch -t "202403010000" /tmp/backup/cron/cron-20240301.gz
$ touch -t "202403020000" /tmp/backup/cron/cron-20240302.gz

それぞれのディレクトリ内に作成されたことを確認します。

$ pwd
/tmp/backup/messages
$ ll
合計 4
-rw-r--r--. 1 root root  0  3月  1 00:00 messages-20240301.gz
-rw-r--r--. 1 root root  0  3月  2 00:00 messages-20240302.gz
-rw-r--r--. 1 root root 38  4月  5 00:00 messages-20240405.gz

$ pwd
/tmp/backup/cron
$ ll
合計 4
-rw-r--r--. 1 root root  0  3月  1 00:00 cron-20240301.gz
-rw-r--r--. 1 root root  0  3月  2 00:00 cron-20240302.gz
-rw-r--r--. 1 root root 34  4月  5 00:00 cron-20240405.gz

再びスクリプトを実行し、ログの出力を確認してみます。

2024/04/06 20:39:55: [info] ログバックアップを開始します
2024/04/06 20:39:55: [info] /var/log/messages-20240405のバックアップが成功しました
2024/04/06 20:39:55: [info] 保存期間切れの messages の削除を開始します
2024/04/06 20:39:55: [info] 削除ファイル: messages-20240301.gz,messages-20240302.gz
2024/04/06 20:39:55: [info] 保管期間切れ messages の削除が成功しました
2024/04/06 20:39:55: [info] ログバックアップを開始します
2024/04/06 20:39:55: [info] /var/log/cron-20240405のバックアップが成功しました
2024/04/06 20:39:55: [info] 保存期間切れの cron の削除を開始します
2024/04/06 20:39:55: [info] 削除ファイル: cron-20240301.gz,cron-20240302.gz
2024/04/06 20:39:55: [info] 保管期間切れ cron の削除が成功しました

それぞれ

  • /tmp/backup/messages
  • /tmp/backup/cron
    の中身を確認してみます。
$ pwd
/tmp/backup/messages
$ ll
合計 4
-rw-r--r--. 1 root root 38  4月  5 00:00 messages-20240405.gz

$ pwd
/tmp/backup/cron
$ ll
合計 4
-rw-r--r--. 1 root root 34  4月  5 00:00 cron-20240405.gz

このように保管期間の過ぎたファイルの削除も問題なく行われていますね。

エラーを起こしてみた

以下の通りわざと存在しないコマンドに置き換えます。

# バックアップ対象の存在確認、存在していればバックアップ処理
	if [[ -f "${log}" ]];then
		# Agzipという存在しないコマンドにしてみます
		Agzip -fk "${log}" 2>> "${backup_log}"
		rc1=$?

では、実行してログを確認してみます。

2024/04/06 20:48:56: [info] ログバックアップを開始します
/home/test/test.sh: 行 37: Agzip: コマンドが見つかりません
mv: '/var/log/messages-20240405.gz' を stat できません: そのようなファイルやディレクトリはありません
2024/04/06 20:48:56: [error] /var/log/messages-20240405のバックアップが失敗しま した
2024/04/06 20:48:56: [info] 保存期間切れの messages の削除を開始します
2024/04/06 20:48:56: [info] 保存期間切れの messages は存在しませんでした
2024/04/06 20:48:56: [info] ログバックアップを開始します
/home/test/test.sh: 行 37: Agzip: コマンドが見つかりません
mv: '/var/log/cron-20240405.gz' を stat できません: そのようなファイルやディレクトリはありません
2024/04/06 20:48:56: [error] /var/log/cron-20240405のバックアップが失敗しました
2024/04/06 20:48:56: [info] 保存期間切れの cron の削除を開始します
2024/04/06 20:48:56: [info] 保存期間切れの cron は存在しませんでした

このように、失敗判定と標準エラー出力がログに書き込まれていますね。

最後に

まだまだ初学者ということもありスクリプトの記述に無駄や改善点が多くあるかもしれません。
何かアドバイス等あれば是非、コメントで教えていただけると幸いです。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?