2012年6月19日火曜日

第2水曜日にcronスケジュールしたい

第2水曜日および第3水曜日にcronスケジュールしたいと思ったのですが、調べてみるとcronで指定可能なパターンでは、スケジュールできないことを知りました。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=20020&forum=10

ZFS ファイルシステムの scrub 処理 (整合性チェック) を定期的に動かしたいのですが、zfs-fuse に標準で備わっている設定方法だと、毎週行うか否かの2択になっており、それはちょっと動かし過ぎと思いました。
RAIDZ と RAIDZ2 の2つのストレージプール (tank1, tank2) を作成して ZFS を利用していますが、tank1 は月1回、tank2 は2ヶ月に1回の頻度で scrub を動かしたいため、前述の URL の情報を参考に、自作スクリプトを作りました。どなたかの参考になれば幸いと思いますので、掲載します。
#!/bin/bash
#
# Name: my-zfs-fuse-scrub
#

TARGET=""
if [[ "$1" = 20??-??-?? ]] ; then
    TARGET="-d $1"
elif [ -n "$1" ] ; then
    echo "Usage: my-zfs-fuse-scrub [YYYY-MM-DD]" 1>&2
fi

MONTH=`date +%-m $TARGET`
DAY=`date +%-d $TARGET`
WEEKDAY=`LANG=C date +%a $TARGET`

get_W() {
    local D=$1
    local F L
    for W in 1 2 3 4 5
    do
        F=$((1+($W-1)*7))
        L=$((F+6))
        if let "$F <= $D && $D <= $L" ; then
            break
        fi
    done
}

test_get_W() {
    local D
    for D in `seq 1 31`
    do
        get_W $D
        printf "D=%-2d W=%d\n" $D $W
    done
}
##DEBUG## test_get_W && exit 1

get_W $DAY

if [ "$W,$WEEKDAY" = "2,Wed" ] ; then
    if [ -z "$TARGET" ] ; then
        /usr/bin/zpool scrub tank1
    else
        echo "DEBUG: zpool scrub tank1 run @ $1"
    fi
fi

if [ "$W,$WEEKDAY" = "3,Wed" ] && let "$MONTH%2 == 0" ; then
    if [ -z "$TARGET" ] ; then
        /usr/bin/zpool scrub tank2
    else
        echo "DEBUG: zpool scrub tank2 run @ $1"
    fi
fi

exit 0
これを、次のように crontab に登録することで、毎月第2水曜日 AM1:00 に tank1 の scrub を実行、偶数月の第3水曜日 AM1:00 に tank2 の scrub を実行するようにスケジューリングしました。
0 1 * * Wed /root/bin/my-zfs-fuse-scrub
なお、実行日を確認し易いように、デバッグ機能をつけてあります。
# cal 6 2012
      June 2012
Su Mo Tu We Th Fr Sa 
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

# ./my-zfs-fuse-scrub 2012-06-13
DEBUG: zpool scrub tank1 run @ 2012-06-13
# ./my-zfs-fuse-scrub 2012-06-20
DEBUG: zpool scrub tank2 run @ 2012-06-20
# ./my-zfs-fuse-scrub 2012-06-27
#
# cal 7 2012
      July 2012
Su Mo Tu We Th Fr Sa 
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

# ./my-zfs-fuse-scrub 2012-07-11
DEBUG: zpool scrub tank1 run @ 2012-07-11
# ./my-zfs-fuse-scrub 2012-07-18
#
さあこれで、まずは、今晩深夜 1:00 に tank2 への scrub がちゃんと動くはず...何か間違いを犯していなければ。。

2012-06-23追記
ログを確認したところ、うまく行っていました。
# cat /var/log/cron
...
Jun 20 01:00:01 xxxx CROND[28792]: (root) CMD (/root/bin/my-zfs-fuse-scrub)
...
# zpool status

  pool: tank1
 state: ONLINE
 scrub: none requested
config:

...

errors: No known data errors

  pool: tank2
 state: ONLINE
 scrub: scrub completed after 0h42m with 0 errors on Wed Jun 20 01:42:50 2012
config:

...

errors: No known data errors
次は、7/11 (第2水曜) に tank1 の scrub が動き、7/18 (第3水曜日 && 奇数月) には tank2 への scrub が行われない、というふうにプログラムできたはずです。

2012-07-20追記
その後のログを確認したところ、意図した通りに動作していました。
# who -b
         system boot  2012-07-03 12:14
# uptime
 08:07:13 up 14 days, 19:53,  3 users,  load average: 0.12, 0.09, 0.09
# uname -a
Linux xxxx 2.6.32-220.13.1.el6.x86_64 #1 SMP Tue Apr 17 23:56:34 BST 2012 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/redhat-release 
CentOS release 6.3 (Final)
# grep zfs-fuse /var/log/cron
Jul  3 13:26:01 xxxx run-parts(/etc/cron.weekly)[12348]: starting 98-zfs-fuse-scrub
Jul  3 13:26:01 xxxx run-parts(/etc/cron.weekly)[12355]: finished 98-zfs-fuse-scrub
Jul  4 01:00:01 xxxx CROND[41538]: (root) CMD (/root/bin/my-zfs-fuse-scrub)
Jul 10 03:10:01 xxxx run-parts(/etc/cron.weekly)[30291]: starting 98-zfs-fuse-scrub
Jul 10 03:10:01 xxxx run-parts(/etc/cron.weekly)[30298]: finished 98-zfs-fuse-scrub
Jul 11 01:00:01 xxxx CROND[4220]: (root) CMD (/root/bin/my-zfs-fuse-scrub)
Jul 17 03:37:01 xxxx run-parts(/etc/cron.weekly)[43573]: starting 98-zfs-fuse-scrub
Jul 17 03:37:01 xxxx run-parts(/etc/cron.weekly)[43580]: finished 98-zfs-fuse-scrub
Jul 18 01:00:01 xxxx CROND[15841]: (root) CMD (/root/bin/my-zfs-fuse-scrub)
# zpool status | grep scrub:
 scrub: scrub completed after 1h13m with 0 errors on Wed Jul 11 02:13:35 2012
 scrub: none requested
# zpool status
  pool: tank1
 state: ONLINE
 scrub: scrub completed after 1h13m with 0 errors on Wed Jul 11 02:13:35 2012
config:

...

errors: No known data errors

  pool: tank2
 state: ONLINE
 scrub: none requested
config:

...

errors: No known data errors

これであとは、5年くらい運用・利用できたら、コスト(投資額+構築労力)に見合うかなと思います。

2015-02-10追記
備忘録。この記事を書いた当時は zfs-fuse を使ってたが、その後、ZFS on Linux に切り替えて継続利用中。
当時新品の HDD (ちなみに全て AFT の 2.5inch 7200rpm 750G)で組んで、2年半経過しましたが、今のところ不良セクタはありません。
人気ブログランキングへ にほんブログ村 IT技術ブログへ