Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

バッチあるある

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

php

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

yuki777
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした