LoginSignup
45
47

More than 1 year has passed since last update.

cronとshellとphpと標準出力とエラー出力とアラートとログローテート

Last updated at Posted at 2013-07-03

バッチあるある

  • 出力全部捨ててる!
  • ログがディスク圧迫!
  • アラートが飛んでこないとか、 エラーでもないのにメールが来る!
  • メール送信処理、ログファイル処理、ログローテート、、、などの本質的じゃないところの仕様どうしようとか、バグとか。

php

test.php
<?php
if(!defined('STDIN'))  define('STDIN',  fopen('php://stdin',  'rb'));
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'wb'));
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'wb'));

// これらは標準出力
echo "this is php debug message by echo()\n";
fputs(STDOUT, "this is php debug message by fputs(STDOUT).\n");
file_put_contents('php://stdout', "this is php debug message by file_put_contents(php://stdout).\n");

// こいつらはエラー出力
fputs(STDERR, "this is php error message by fputs(STDERR).\n");
file_put_contents('php://stderr', "this is php error message by file_put_contents(php://stderr).\n");
// これもエラー出力
trigger_error("trigger_error E_USER_NOTICE", E_USER_NOTICE);
trigger_error("trigger_error E_USER_WARNING", E_USER_WARNING);
trigger_error("trigger_error E_USER_ERROR", E_USER_ERROR);

exit(0); // 正常終了
exit(1); // 異常終了exit(1-254);

  • 標準出力、エラー出力を分けよう
  • 正常終了、異常終了を分けよう
  • echo, fputs,などを色んな所に書くのではなく、ラッパー関数を作ってそれを呼ぶといいはず。logDebug($msg); logError($msg);とか。

shell

test.bash
#!/bin/bash

function create_pid {
    echo $$ > $pid_file
}

function delete_pid {
    rm $pid_file
}

function check_pid {
    if [ -f $pid_file ]; then
        pid=`cat $pid_file`
        if (ps -e | awk '{print $1}' | grep $pid >/dev/null); then
            echo "${0} is runnning, exit"
            exit 1
        fi
    fi
}

function main {
    echo "this is bash debug message." # 標準出力
    echo "this is bash error message. 1>&2" 1>&2 # エラー出力

    check_pid  # 多重起動なら終了
    create_pid # 多重起動チェック用ファイルを作成

    # 外部プログラム実行して終了ステータスを判定
    $batch_cmd
    if [ $? -gt 0 ]; then
        delete_pid # 多重起動チェック用ファイルを削除
        exit 1 # 異常終了1-255
    fi

    delete_pid # 多重起動チェック用ファイルを削除
    exit 0 # 正常終了
}

pid_file="/tmp/mazda-test-script-pid.`hostname`"
batch_cmd="/usr/bin/php /path/to/mazda/test.php"
main
  • 標準出力、エラー出力を分けよう
  • 外部プログラムの終了ステータスを判定しよう
  • 正常終了、異常終了を分けよう
  • 多重起動防止しておこう

cron

crontab
# メールを送らない設定。コメントには日本語も使えます
MAILTO=""

# MAILTOを上書きできます
MAILTO="yuki.mazda+foo@bar.com"
* * * * * cd /path/to/mazda; /bin/bash /path/to/mazda/test.bash >> /path/to/mazda/logs/`date +\%Y\%m\%d`.log

# MAILTOには複数のアドレスが設定出来ます
# 複数アドレスの時はダブルクォートなしで、,のあとのスペースもなしじゃなきゃダメかも?
MAILTO="yuki.mazda+hoge@hoge.com, yuki.mazda+hoge@foo.com"

# 1ヶ月前のログをfindして削除する
0 10 * * * find /path/to/mazda/logs/ -type f -name "`date +\%Y\%m\%d --date '1 month ago'`.log" -exec rm -f {} \;

# この例ではもともとメールを送らない設定だったのでもとに戻しておこう
MAILTO=""
  • cronには出力をメール送信する機能があります。送信先はMAILTOで変えられます。MAILTO=""ならメール送信しません
  • cron行ごとにMAILTOを設定できます。上書きできます
  • 標準出力をログファイルにリダイレクトしよう
  • ログファイルは20130620.logみたいな形式にしておこう
  • 古いログファイルは適当に削除するcronもセットする
  • プロジェクトルートにcdしておいたほうが楽できるよ
  • 権限気にしなくて済むので/bin/bash /path/to/scriptが楽

こうすると

  • デバッグログは必要な分だけ保存され続けるし、不要なメールは飛んで来ないし、エラーがあった時だけアラートが来る
  • すでにあるlinuxアーキテクチャでつくるので、メール送信処理、ログファイル処理とか、むだに仕様決めなくて済む
  • ちゃんと正常終了、異常終了のステータスを分けておくと/var/log/syslogにそれっぽく出てくれます。

そうは言っても

  • fluentdでログったりもありえるし、個別にアラートメールしたりもする。ログファイルを自前で処理したり。アプリケーションによってはこれらは必要です。好きにすればいいよ
  • フレームワークがあるならそれを使えば良いとおもいます。
45
47
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
45
47