[Server & Network General] Crontab: スクリプトを定期的に実行しログを残す

crontab の動作に関して確認してみました。

準備

レンタルサーバでやってみます。
つづきのような感じです。

こんなディレクトリを用意します。

  • ~/sbin … cron で走らせるスクリプト
  • ~/var/log … スクリプトの実行結果
  • ~/var/com.example.www … mysqldumpファイル置き場

path を通すついでに、crontab -r の悲劇を起こさないよう、alias も作っておきます。

$ mkdir sbin
$ mkdir var
$ mkdir var/log
$ mkdir var/com.example.www
$ vim .zprofile
$ source ~/.zprofile
~/.zprofile
# Custom Path
export PATH=$PATH:$HOME/bin/:$HOME/sbin/
# cron
alias crontab='crontab -i'

crontab -e でこんな感じに設定します。

crontab
MAILTO='alert@example.com'
HOME='/home/myuser/'
LOG_DIR='/home/myuser/var/log'
15 * * * *  /bin/zsh $HOME/sbin/blog_mysqldump.sh

実行スクリプトはこのようにしてみました。
例外処理とかどう書けば良いかいまいち分かってない感じです。

~/sbin/blog_mysqldump.sh
#! /bin/zsh
bak_days=7
dest=/home/myuser/var/com.example.www
datetime=`date +%F_%T`
timestamp=`date +%Y%m%d`
limit=`date "-d $bak_days days ago" +%Y%m%d`
function backup {
    bakfile=$dest/$timestamp.bak.sql.bz2
    mysqldumpp --opt --all-databases | bzip2 -c > $bakfile
    echo "$datetime Create: $bakfile"
}
function cleanup {
    rmfile=$dest/$limit.bak.sql.bz2
    rm -f $rmfile
    echo "$datetime Delete: $rmfile"
}
backup
cleanup

/dev/null でログを捨てない

Cron Daemon からメール通知

上記のような準備をすると、ディフォルトの挙動として MAILTO に設定したメールアドレスへ結果ログを送ってくれます。

成功時

From: root@example.com (Cron Daemon)
To: alert@example.com
Subject: Cron <root@example.com> /bin/zsh $HOME/sbin/blog_mysqldump.sh
2013-09-15_12:10:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:10:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2

スクリプト内の echo が本文となっています。
ちなみに echo なしではメールが送信されませんでした。

失敗時

mysqldumpp と間違ったコマンドを書いてみました。

From: root@example.com (Cron Daemon)
To: alert@example.com
Subject: Cron <root@example.com> /bin/zsh $HOME/sbin/blog_mysqldump.sh
backup:2: command not found: mysqldumpp
2013-09-15_12:10:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:10:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2

function backup の 2行目のコマンドが見つからない、ということでしょうか。

ログファイルに残す

レンサバなので自前ログに残す方法で。
ほんとうはログローテションしないといけない。

*/10 * * * *  /bin/zsh $HOME/sbin/blog_mysqldump.sh >> $LOG_DIR/blog_mysqldump 2>&1

2>&1 について

成功時

$ tail -f ~/var/log/blog_mysqldump
2013-09-15_12:10:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:10:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2
2013-09-15_12:20:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:20:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2

失敗時

$ tail -f ~/var/log/blog_mysqldump
2013-09-15_12:10:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:10:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2
backup:2: command not found: mysqldumpp
2013-09-15_12:20:01  Create: /home/myuser/var/com.example.www/20130915.bak.sql.bz2
2013-09-15_12:20:01  Delete: /home/myuser/var/com.example.www/20130908.bak.sql.bz2

メール通知&ログに残す

2>&1 | mail

pipe で mail コマンドを叩いてみます。

*/10 * * * *  /bin/zsh $HOME/sbin/blog_mysqldump.sh >> $LOG_DIR/blog_mysqldump 2>&1 | mail $MAILTO

メッセージとサブジェクトが空です。
成功したのか失敗したのか分かりません。

From: root@example.com (Cron Daemon)
To: alert@example.com
Subject: Cron <root@example.com> /bin/zsh $HOME/sbin/blog_mysqldump.sh >> $LOG_DIR/blog_mysqldump 2>&1 | mail $MAILTO
No message, no subject; hope that's ok

1> /dev/null

標準出力を捨て、標準エラー出力をメールで送信する設定。
うまい書き方が分かりませんでした。これだとログには残らない。

*/10 * * * *  /bin/zsh $HOME/sbin/blog_mysqldump.sh 1> /dev/null
From: root@example.com (Cron Daemon)
To: alert@example.com
Subject: Cron <root@example.com> /bin/zsh $HOME/sbin/blog_mysqldump.sh 1> /dev/null
backup:2: command not found: mysqldumpp

例外処理も含め、スクリプト内でできるようにすべきなのかもしれない。
また修行ですね。