こんにちは。卓司です。
前回のサーバーの負荷を手軽に確認するシェルスクリプトを作ってみた。や、前々回の特定のファイルを一つのディレクトリに移動させるでは、皆様からのあたたかいご指導・ご鞭撻、誠にありがとうございました。
今回もまた、性懲りもなくシェルスクリプトについてまとめさせていただきますので、何かお気づきの点などありましたら大変お手数ではありますが、ご指摘いただけるととても嬉しいです。
1. 経緯
今PHPでプログラミングしてるんです。その時になんかの間違えでERRORが出たり、WARNINGが出たり、NOTICEが出たり。。。
出さないよう出さないよう組んではいるのですが、忘れた頃にポロッと。。。
実装に集中してしまうと中々ログまで気がまわらなくなってしまうんですよね。。。
毎日一回でいいから、ログの中身を見て、最低でもERRORとWARNINGは取り除きたいなって思うんです。。。
そこで、一日一回ログの中身を見てERRORとWARNINGがあったら一報くれる仕組みがあったら便利だと思い、作ってみました。
2. 機能概要
PHPのログファイルにERRORまたはWARNINGが出てたら、指定メールアドレスに一報くれる。
あと、検索は『ログ全部を検索できるパターン』と、『前日のログだけ検索できるパターン』があったらいいですね。
二つの処理パターンを上げた理由は、シェルスクリプトを組み込む際に一度ログを全体を検索して、あとは毎日その前日分だけを検索するよう運用したいためです。
上記の処理を箇条書きにするとこんな感じでしょうか。
- 全ログ検索の指定があった場合、全ログ検索を実行
- 前日分ログ検索の指定があった場合、前日分ログ検索を実行
- 検索結果の行数が0以上だった場合、指定メールアドレスに連絡メール送付
では、上記の処理を元にシェルスクリプトを作ってみます。
3. 作成したシェルスクリプト
作成したシェルスクリプトは以下の通りです。
#/bin/sh
##############################################################
## ファイル名: checkLog ##
## 処理内容 : 指定ログの定時確認処理 ##
##############################################################
# 確認対象ログの参照先
systemName='NAKADA Project'
# 確認対象ログの参照先
checkLogPath='/var/log/httpd/error_log'
# 検索するErrorメッセージ文言
targetError='[error]'
# 検索するWarningメッセージ文言
targetWarning='[warning]'
# 検索するNoticeメッセージ文言
targetNotice='[notice]'
# 実行時間取得
nowTime=`date "+%Y%m%d%H%M%S"`
########################
## 結果メール送付設定 ##
########################
# 結果メールの宛先 ※カンマ区切りで複数宛先に送信可能
mailTo='宛先メールアドレス'
# 結果メールのCC ※カンマ区切りで複数CCに送信可能
mailCc='CCメールアドレス'
# 結果メール送信元
mailFrom='送信元メールアドレス'
# 結果メールタイトルヘッダ
mailTitleHeader="[CheckPHPLogReport:$systemName:$nowTime] "
###############################
# MAIL送信
###############################
send_mail(){
mailBody=$1
mailTitle=$mailTitleHeader$2
mailTo=$3
mailFrom=$4
echo -e $mailBody | mail -c $mailCc -s "$mailTitle" $mailTo -- -f $mailFrom
}
# 確認対象ログの存在確認
if [ ! -f $checkLogPath ]; then
# 選択したログファイルが存在しない
send_mail "No such file or directory in [$checkLogPath]." 'ERROR!! no log file!!' "$mailTo" "$mailFrom"
exit
fi
result=0
reportType='all'
if [ ! $1 ]; then
# 日付未指定の場合
# 検索
result=`grep "$targetError|$targetWarning" $checkLogPath | wc -l`
else
# 日付指定の場合
# 引数確認
agoDay=0
if [ $1 -gt 0 ]; then
agoDay=$1
else
# 引数が不正
send_mail "Missing argument 1.nArgument is zero or more.narg:$1" 'SCRIPT ERROR!! Missing argument 1.' "$mailTo" "$mailFrom"
exit
fi
# 検索日付取得
nowYear=`date -d "$agoDay days ago" "+%Y"`
nowMonth=`LANG=C date -d "$agoDay days ago" "+%b"`
nowReportMonth=`date -d "$agoDay days ago" "+%m"`
nowDay=`date -d "$agoDay days ago" "+%d"`
nowWeekDay=`LANG=C date -d "$agoDay days ago" "+%a"`
targetDay="[$nowWeekDay $nowMonth $nowDay [0-9]{2}:[0-9]{2}:[0-9]{2} $nowYear]"
# 検索
result=`grep "$targetDay" $checkLogPath | grep "$targetError|$targetWarning" | wc -l`
reportType=$nowYear$nowReportMonth$nowDay
fi
# 結果出力
if [ $result > 0 ]; then
# ログにERRORまたは、WARNING有
send_mail "Warning or Error occurred with the log file[$checkLogPath].($result)" "ERROR no WARNING occurred!!(type:$reportType)" "$mailTo" "$mailFrom"
fi
exit
注意点
- ログのレイアウトはデフォルト状態のものを対象としています。異なるフォーマットだと正しく検索できません。
- エラーメッセージは文字化けを嫌って英語にしてます。その英語が苦手ときているので怪しいものが。。。
- ERRORやWARNINGの詳細がメールで記載されているわけではないです。メールを受信したらログを確認してください。
4. 使い方
本シェルスクリプトの使い方を以下にまとめます。
4 – 1. 前作業
本スクリプトを実行する前には以下の変数を修正してください。
1.systemName=
対象となるシステム名を格納してください。
2.checkLogPath=
確認対象となるログファイルのフルパスを格納してください。
3.mailTo=
送付先メールアドレスを格納してください。※カンマ区切りで複数格納可
4.mailCc=
CC対象メールアドレスを格納してください。※カンマ区切りで複数格納可
5.mailFrom=
送付元メールアドレスを格納してください。
4 – 2. 検索
本スクリプトの実行パターンは以下の通りです。
1.全検索
対象ログ全体を検索するパターンです。
checkLog.sh
2.前日検索
対象ログの前日分のみ検索するパターンです。
checkLog.sh 1
一度全検索を行い、あとはクーロンで前日検索を日々行えばまぁまぁ使えない事はないかなと思います。
5. まとめ
これで毎晩実装したログが出てくるわけです。
開発段階でがりがりプログラムを書いてる時はとりわけ見落としがちなエラーログもこれでいくらかカバーできるかと思います。
もっといい方法や便利な方法があるとは思うのですが、とりあえずこれで当面はエラーを確認しようと思います。
もし、よろしければ使ってみてください。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。