※Mackerelアンバサダープログラムに参加しています
背景
管理しているサーバー上でcronによって起動するスクリプトが多数あり、同じスクリプトが多重起動しないように設定してあります。5分に一度動くスクリプトが状況によっては5分以上処理時間がかかる場合、処理が完了するまでは次のプロセスが起動しないようになっています。
この状況で運用していたのですが、ある日とあるプロセスがフリーズしてしまったのか終わらなくなってしまっていました。そして多重起動防止のおかげで新しいプロセスが起動せず、必要な処理が数日間実行されていないトラブルが起きました。
この状況になるべく早く気づけるよう、プロセス稼働時間が閾値を超えると通知されるようにします。
※今回の対象サーバーはUbuntuなので、Ubuntu前提の説明になります。また既にMackerelエージェントはインストール済み、稼働済みの前提です。
Mackerelのcheck-procsプラグインの設定
Mackerelのcheck-procsプラグインで監視が出来ます。
check-procsプラグインをインストールします。
sudo apt-get install mackerel-check-plugins
/etc/mackerel-agent/mackerel-agent.confに以下の設定を追記します。
今回は、プロセス名にphpを含む(ただし、test1, test2のどちらかの文字が含まれるプロセスは対象にしない)という設定例です。実行時間が1時間を超えるプロセスが一つでもあるとcriticalアラートが出るようにしています。
[plugin.checks.php_long_running]
command = ["check-procs", "--pattern", "php", "--exclude-pattern", "(test1|test2)", "--esec-over", "3600", "--critical-over", "0", "--warning-under", "0", "--critical-under", "0"]
対象となるプロセスが一つ以上あるとアラートを発生させる場合のtipsが公式ドキュメントに記載されているので、それを参考にしました。
Mackerelのカスタムメトリックで、プロセスの実行時間を記録する
上記までの設定で長時間稼働するプロセスを通知出来るようになったのですが、プロセスの処理内容によって数秒で終わるものもあれば1時間くらい掛かるものもあり通知の閾値をどのくらいにすればいいか実際の処理時間の記録を見て決めていきたいと思いました。
Mackerelのカスタムメトリック投稿機能でプロセス実行時間を記録することにしました。
上記記事を見ながら作成していきます。
プロセスの稼働時間とプロセス名( & 引数)は以下のコマンドで取得出来ます。
ps -eo etimes,args
例えば以下のようにするとmackerel-agentの稼働時間(秒数)が見えます
$ ps -eo etimes,args | grep mackerel
0 grep --color=auto mackerel
504816 /usr/bin/mackerel-agent supervise --root /var/lib/mackerel-agent
504816 /usr/bin/mackerel-agent --root /var/lib/mackerel-agent -child
これを使ってカスタムメトリックの形式になるよう整形するシェルスクリプトを作りました。
#!/bin/bash
NOW=$(date +%s)
PATTERN="php"
EXCLUDE="test1|test2|grep"
ps -eo etimes,args | grep "$PATTERN" | grep -vE "$EXCLUDE" | while read -r line; do
# 最初のフィールド(秒数)を取得
ELAPSED=$(echo "$line" | awk '{print $1}')
# phpに渡されている引数を取得(メトリック名にする)
# 例: php artisan hoge1 hoge2 -> artisan hoge1 hoge2
FULL_COMMAND=$(echo "$line" | sed -e "s/^[0-9]* //" -e "s|.*/php ||")
# メトリック名として使えない文字(スペース、スラッシュなど)をアンダースコアに変換
METRIC_NAME=$(echo "$FULL_COMMAND" | tr ' /:' '___' | sed 's/_\+/_/g')
# Mackerel形式で出力
# custom.php_proc.elapsed.[メトリック名]
echo "custom.php_proc.elapsed.${METRIC_NAME} ${ELAPSED} ${NOW}"
done
実行権限を与えます。
chmod +x mackerel-proc-time.sh
mackerel-agent.confに以下のように追記します。(作成したシェルスクリプトのフルパスをcommandに指定)
[plugin.metrics.php_processes]
command = "/home/user/mackerel-proc-time.sh"
mackerel-agentを再起動
sudo systemctl restart mackerel-agent
これで、毎分対象プロセスの実行時間がホストのメトリックとして見られるようになります。