仮想マシン (以下 VM) のバックアップ・スクリプトに限らず、 VMware ESXi 4.0 で cron を使おうとすると、ESXi ならではのハードルが登場する。

crontab が存在しない ESXi では、/var/spool/cron/crontabs/root を直接編集して crond を再起動させることで、cron ジョブを追加・変更できる。ただ ESXi を再起動させると綺麗サッパリ消されてしまうのが惜しい、と言うか決定的に使えないので、対策が必要になる。

ジョブを自由に登録できない (※ 正確には ESXi 起動時にリセットされてしまう) cron など無用の長物にも思えるが、"unsupported" な先人が開拓してくれた、「消されないようにする」 のではなく 「消されてもしつこく登録し直す」 と言う発想の転換で、(一応) 克服できた。

具体的には、/etc/rc.local に cron ジョブを登録 → crond を再起動する処理を書き、毎回 ESXi の起動時に強引に登録し直す、と言う方法だ。crond の pid の特定に awk を使った短い方法を何箇所かで見かけたが、そのまま真似するのも芸がないので、実際の処理は以下のようにした。

# crontab
crontab='/var/spool/cron/crontabs/root'
if [ -f ${crontab} ]; then
        ps aux | grep -v grep | grep crond > /dev/null 2>&1 ← crond の動作を確認
        [ $? -eq 0 ] \
                && kill -TERM `ps aux \ ← crond の pid を特定して停止
                        | grep -v grep \
                        | grep crond \
                        | sed 's/  */ /g' \
                        | cut -d ' ' -f 1`
        cat << _END_ >> ${crontab} ← cron ジョブを追加
0 22 * * * <SCRIPT> ← バックアップ・スクリプトのフルパス
_END_
        crond ← crond を起動
fi

尚、ESXi は NTP で外部から時刻を取得できるが、内部のシステム時刻は UTC のため、cron ジョブの時刻も UTC で登録する必要があるし、バックアップ用スクリプト中で利用する date の結果も UTC だ。少々気持ち悪いが、こう言うものだと諦めている。

また cron にバックアップの処理を VM の数だけ列挙するのもあまり美しくないので、ESXi のインベントリに登録された VM を日替わりでバックアップ・スクリプトに投げるスクリプトを別途用意し、これを cron に登録した。

ところで、ESXi の /etc/rc.local にはデフォルトで以下の記述がある。

#execute all service retgistered in /etc/rc.local.d
if [ -d /etc/rc.local.d ]; then
   for filename in `find /etc/rc.local.d/ | sort`
      do
         if [ -f $filename ] && [ -x $filename ]; then
            log "running $filename"
            $filename
         fi
      done
fi

これを発見した時は、/etc/rc.local.d ディレクトリに実行属性の付いたスクリプトを放り込んでおけば、"-f" と "-x" が冗長な気もするが、ESXi 起動時にファイル名順にログに残しつつ実行されるに違いない、と喜んだ。ユーザーが追加したファイルは何でも起動時に消してしまうのではなく、ちゃんと抜け道が用意してあるとは感心感心、とディレクトリを作成し、上記の cron ジョブ追加をはじめスクリプトをいくつか設置して ESXi を再起動してみると、/etc/rc.local.d ディレクトリごと跡形もなくなっていた。面白いトラップだ。動かないだけならまだしも、削除するとは何事か。(ESX ではちゃんと機能したりするんだろうか?)

Comments are closed.