Bashでファイルのサイズ監視とローテートをする
最近はどんなスクリプトもGolangで書くようにしているのであまりないんですが、
会社ではGolangを導入できていないので、Bashでスクリプトを書くことも少なくないです。
その中でもそこそこ多いのが、エラーログなどの監視スクリプト。
丁度今日、これで完成版でいいかなーってのができたので、
どういうことをしているかを自分のために残しとく。
大まかな処理の流れ
どのファイルを監視するかを配列で定義
配列を順に回す
ファイルが存在しているかチェック、存在していれば続く処理を、存在しなければファイル配列の次の要素へ
ファイルのサイズを取得
ファイルサイズが0でなければエラーが出ているので続く処理を、0ならファイル配列の次の要素へ
Slackにログファイルのサイズが変わっている通知を送信
既存のログを複製してファイル名にタイムスタンプをつける
既存のログを空(0バイト)にする
ファイル配列の次の要素へ
全てのファイル配列を処理し終わったら終わり
実際のコードと解説
code:check_log.sh
SYSTEM_NAME="example system"
FILES=("./logs/std.out" "./logs/error.log")
for FILE in ${FILES@}; do FILE_SIZE=$(ls -l ${FILE} | awk '{print $5}')
NEW_FILE_NAME=${FILE}."$(date '+%Y%m%d%H%M%S')"
curl -s -S -X POST --data-urlencode "payload={\"text\": \"${SYSTEM_NAME}\n${FILE}に出力がありました\nファイル名: ${NEW_FILE_NAME}\" }" ${WEBHOOK_URL} >/dev/null
cp ${FILE} ${NEW_FILE_NAME}
: >${FILE}
fi
fi
done
WEBHOOK_URL : SlackのIncoming Webhookのエンドポイント
SYSTEM_NAME : 通知時にどこからの通知か分かるように名前を付けてます
FILES : 監視するファイルの一覧です
文字列をスペース区切りでカッコに入れていて、これは2つの要素を持つ配列です
for FILE in ${FILES[@]}; do done : 他言語でいうforeachです
FILESの内容を一つずつ取り出して、FILEに代入します
if [ -f $FILE ]; then fi : ファイルの存在チェックです。ファイルがあるときにthen以下が実行されます
FILE_SIZE=$(ls -l ${FILE} | awk '{print $5}') : ファイルサイズを取り出しています
lsコマンドの結果はスペース区切りのようになっているので、それをawkで配列のように使って目的の部分を取り出しています
if [ "${FILE_SIZE}" -ne "0" ]; then fi : 普通のif文です。ファイルサイズが0じゃないときにthen以下を実行します
NEW_FILE_NAME=${FILE}."$(date '+%Y%m%d%H%M%S')" : 新しいファイル名を作っています。末尾のタイムスタンプは年月日時分秒ですね
curl ~ : Slackにメッセージを送信しています
cp ${FILE} ${NEW_FILE_NAME} : ただのコピー
: >${FILE} : 初めて知ったのですが、完全な空(0バイト)を書き込んでます
おわりに
Golangでスクリプトを書くのはユニットテストをしっかりしたいからです。
でも短いスクリプトならbashでサクッと書いちゃうのはいいですよね