no-image

AWSのkusanagi環境のWordPressとPHPでFatal Errorやsintax errorがあったときにSwatchで監視してSlack通知する

少し前にPHPでFatal Errorやsintax errorがあったときにSwatchでメールで通知するをやったのですが、不便だったのでslackで実装しなおしました。

以下が不便だった理由。

  1. AWSの迷惑メール防止フィルタに引っ掛かる
  2. メール通知だと即時性が低い
  3. どのサーバからの通知かわからない

上から順に大きな理由です。

メール通知からslack通知に切り替えた理由

「1.AWSの迷惑メール防止フィルタに引っ掛かる」と「2.メール通知だと即時性が低い」の2つが理由として大きいです。

ちなみにAWSでもきちんと申請すればできるようです。
https://dev.classmethod.jp/beginners/ec2-port-25-throttle/

2.については正確に言うとメール通知の即時性が低いのではなく、常に見ている対象ではないのでエラーが起きた時に気付きにくいなと。 今の環境では社内SNSにslackを使っているので便利かなと思ったので。

実装の流れ

こんな感じで実装します。

  1. シェルスクリプトでslack通知
  2. Swatchの設定
  3. Swatchを常駐させる設定

シェルスクリプトでslack通知

以下の順で準備します。

  1. slackのIncoming Webhookを有効にする
  2. シェルスクリプトを作る
  3. シェルスクリプトに実行権限を与える

slackのIncoming Webhookを有効にする

この辺の情報は世の中にたくさんあるので割愛します。
このサイトがコードも汎用性が高くわかりやすかったです。
https://qiita.com/tt2004d/items/50d79d1569c0ace118d6

シェルスクリプトを作る

コードを先ほどのサイトから拝借。
https://qiita.com/tt2004d/items/50d79d1569c0ace118d6

パーミッションのユーザーはkusanagiでもいいけど、今のところ使う予定無いので一応rootで作りました。

$ sudo su - #ユーザーをrootに変更

「3.どのサーバからの通知かわからない」を解消するために以下を追加しました。

HOSTNAME=$(hostname -I)

/home/kusanagi/bin/slack.sh

#!/bin/sh

set -eu

#Incoming WebHooksのURL
WEBHOOKURL="https://hooks.slack.com/services/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" #メッセージを保存する一時ファイル
MESSAGEFILE=$(mktemp -t webhooks.XXXX)
trap "
rm ${MESSAGEFILE}
" 0

usage_exit() {
echo "Usage: $0 [-m message] [-c channel] [-i icon] [-n botname]" 1>&2 exit 0
}

while getopts c:i:n:m: opts
do
case $opts in
c)
CHANNEL=$OPTARG
;;
i)
FACEICON=$OPTARG
;;
n)
BOTNAME=$OPTARG
;;
m)
MESSAGE=$OPTARG"\n"
;;
\?)
usage_exit
;;
esac
done

#どのサーバからの通知かわかるようにip取得
HOSTNAME=$(hostname -I)
#slack 送信チャンネル
CHANNEL=${CHANNEL:-"#php_notification"}
#slack 送信名
BOTNAME=${BOTNAME:-"Swatch"}
#slack アイコン
FACEICON=${FACEICON:-":sos:"}
#見出しとなるようなメッセージ
MESSAGE=${MESSAGE:-$HOSTNAME}

if [ -p /dev/stdin ] ; then
#改行コードをslack用に変換
cat - | tr '\n' '\r' | sed 's/'"$(printf '\r')"'/\\n/g' > ${MESSAGEFILE} else
echo "nothing stdin"
exit 1
fi

WEBMESSAGE='```'`cat ${MESSAGEFILE}`'```'

#Incoming WebHooks送信
curl -s -S -X POST --data-urlencode "payload={\
\"channel\": \"${CHANNEL}\",\
\"username\": \"${BOTNAME}\",\
\"icon_emoji\": \"${FACEICON}\",\
\"text\": \"${MESSAGE} ${WEBMESSAGE}\" }" ${WEBHOOKURL} >/dev/null #1>&2 #デバッグの時は1>&2をコメントアウトしないと、slackのwebhookのエラーステータスが表示されて便利 

シェルスクリプトに実行権限を与える

$ chmod 700 /home/kusanagi/bin/slack.sh

Swatchの設定

Swatchのダウンロードや設定はこちらの記事を参考にしてください。
[blogcard id=”237″]

Error形式ごとに、kusanagiのlogの吐き出し方が違い、ここでかなりハマりました。
()と””の数や生で出さないようにしないといけない、みたいな工夫が必要です。

正直この辺は環境やlogを残す際の設定によって違うと思いますが、キモになるのは以下の2つです。

1.ダブルコーテーション"の数
swatchに引っ掛かった行のダブルコーテーションの数が奇数だと、「”が閉じてない!」と怒られます。

2.カッコ()が直で書かれてる
swatchに引っ掛かった行に()があると「()はエスケープしろ!」と怒られます。

/etc/swatch/swatch.conf

watchfor /PHP Fatal error/
echo red
exec echo $_" | /home/kusanagi/bin/slack.sh #ダブルコーテーションが1つしかないので末尾に追加 watchfor /recv\(\)/
echo blue
exec echo "$_" | /home/kusanagi/bin/slack.sh #行内に()があるため文字列ということを明示 watchfor /PHP Parse error/
echo yellow
exec echo $_ | /home/kusanagi/bin/slack.sh #
ダブルコーテーションできれいにくくられているために""をつけると逆にうまく出ないのでなにもつけない

logの時点でシングルコーテーション''をつけて出すようにするとかやりようはあるように思いますが、いい手段が見つからず対処療法的ならざるを得ませんでした…いい方法あれば教えてください。

Swatchを常駐させる設定

こちらも詳しくはこちらの記事を参考にしてください。
[blogcard id=”237″]

/etc/init.d/swatch

#!/bin/bash

#chkconfig: 345 80 20
#source function library.
. /etc/rc.d/init.d/functions

start(){
echo -n "starting Swatch: "
/usr/bin/swatch -c /etc/swatch/swatch.conf -t
/home/kusanagi/sitename/log/nginx/error.log & # -t 以降はログファイルの場所を設定 この行を追加すれば複数場所を監視可能
return 0
}
stop(){
killproc swatch
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
esac

実行権限を与える

$ sudo su - #rootユーザーに変更
$ chmod 700 /etc/init.d/swatch #実行権限を付与

自動起動設定

$ sudo /etc/init.d/swatch start #daemonにswatchを追加
$ sudo chkconfig –-add swatch #chkconfigにswatchを追加
$ sudo chkconfig swatch on #chkconfigでswatchをonにする
$ sudo chkconfig --list #chkconfigでswatchが動いてるか確認する

swatch.confの試行錯誤のコード

watchfor        /PHP Parse error|PHP Fatal error|recv\(\) failed/
        echo red
        #exec /home/kusanagi/bin/slack5.sh -m "$*" > /dev/null 2>&1
        #exec "echo kusanagi-stg PHP error | /home/kusanagi/bin/slack.sh"
        #exec cat $0 | sed s/\"//g #ダメ
        #exec echo $0" > /tmp/test.txt #動く
        #exec echo $0 > /tmp/test.txt #閉じ"が無いとエラー出る
        #exec echo $0" | sed s/\"//g #sedの"がダメ
        #exec echo $0 | sed s/\"//g #sedの"がダメ
        #pipe sed s/\"//g #sedの"がダメ
        #exec echo $0" | sed "s/"//g" # sedの構文エラー
        #pipe > /tmp/test.txt #エラーはないけどデータが入らない
        #pipe echo $0" > /tmp/test.txt #動く
        #exec sed s/\\"//g /tmp/test.txt | /home/kusanagi/bin/slack.sh #動く!
        #exec sed s/\\"//g $0 | /home/kusanagi/bin/slack.sh #"が無いとエラーになる
        #exec sed s/\\"//g $0" | /home/kusanagi/bin/slack.sh #実行しようとしてエラー
        #exec  /home/kusanagi/bin/slack.sh sed s/\\"//g $0" #nothing in std
        #exec  /home/kusanagi/bin/slack.sh < sed s/\\"//g $0" #nothing in std no   sed such file
        #exec echo $0" > /tmp/test.txt
        #exec cat /tmp/test.txt | /home/kusanagi/bin/slack.sh
        #exec echo $0" | /home/kusanagi/bin/slack.sh
        #exec /tmp/test.sh $0"
        #exec echo $0" | /tmp/test.sh #動いた
        #exec echo $0" | sed s/\\"//g | sed s/\\(//g | /home/kusanagi/bin/slack.sh #動いたーーーーー
        #exec echo $_" | sed s/\\"//g | sed s/\\(//g | /home/kusanagi/bin/slack.sh #動いたーーーーー2
        #exec echo $_" | sed s/\\"//g | /home/kusanagi/bin/slack.sh #動いたーーーーー3
        exec echo $_ | /home/kusanagi/bin/slack.sh #動いたーーーーー4

pocketlinehatebuimagegalleryaudiovideocategorytagchatquotegoogleplusfacebookinstagramtwitterrsssearchenvelopeheartstaruserclosesearch-plushomeclockupdateeditshare-squarechevron-leftchevron-rightleafexclamation-trianglecalendarcommentthumb-tacklinknaviconasideangle-double-upangle-double-downangle-upangle-downstar-halfstatus