cronでn秒おきに実行するジョブを中途半端な一定期間だけ走らせたい
お題
cronで秒単位で実行しているコマンドを、任意の時間帯だけ走らせたい。
21:50-22:40,22:50-23:40の50mx2の間だけ、n秒おきにとある情報を取るコマンドを走らせたい。
というのを少し苦労したけど、実行ユーザのcronをrootのcronで置き換えるという力業(?)でなんとかできました。
■crontabの基本的な使い方
$ crontab -l
内容表示
$ crontab -e
内容編集
$ crontab -r
内容削除
オプションで - u username をつけるとそのユーザのcronを編集できる。-uつけない場合は現在のユーザのcronに対する操作になる。
ちなみにeとrはキーが隣り合っているため、操作ミスで削除してしまわないようにcrontab -eで編集はしないように、とかエイリアスでcrontab -rを置き換えたり無効にしたりするべきという議論があるけど、ここでは触れない。
自分としては編集前に必ずcrontab -lをしておくことで、間違えて消してしまった場合にすぐ復旧できるようにしておけば良いような気がしているし、実際そうしている。
cronのファイル自体は/var/spool/cron 配下にユーザ名でおいてある(RedHat 7系の場合)ので、そのファイル自体を編集するという手もある。
■crontabの書き方
設定項目は左から「分」「時」「日」「月」「曜日」
* * * * * [実行コマンド]
曜日については0-7で、0も7も日曜日。
リストでの書き方 0,10,20,30 分フィールドの場合0,10,20,30分に実行する
範囲での書き方 1-5 時間フィールドの場合1,2,3,4,5時に実行する。
間隔を指定する */10 分フィールドの場合、10分おきに実行する。
上記のように、デフォルトでは分が最小単位のため、秒指定の実行はできない。
そこでn秒おきに実行するためによく使われるのが、 seq コマンドを使ってfor文を回し、sleepコマンドを使用するもの。
10秒おきの場合はこのように。
* * * * * for i in `seq 0 10 59`;do (sleep ${i}; コマンド) & done;
seqコマンドの動きはこのような感じ。
$ seq 0 10 59 0 10 20 30 40 50 $
上記の場合、0~59の範囲内で10個おきに番号を取得するため、出力としては0,10,20,30,40,50となる。
これを変数iに入れて、sleep $i すると、
sleep 0 実行コマンド sleep 10 実行コマンド sleep 20 実行コマンド sleep 30 実行コマンド sleep 40 実行コマンド sleep 50 実行コマンド
となるので、10秒おきに実行が実現できる。
これを毎分実行するので、毎分00秒になったらseq でsleepする秒を取得し、sleepしてから指定コマンドを実行となる。
■本題-n秒おきに実行するコマンドを、指定時間内だけ実行したい。
ここから本題。
切りの良い時間(1-3時)とか、特定日だけとかなら時間フィールド、日フィールドの記述でなんとかなりそうだし、
張り付いていられる時間なら指定時間にコメントアウトを解除、再度コメントアウトで行けそうだけども。
ちなみに今回のお題は、21:50-22:40,22:50-23:40と非常に中途半端な時間が2回という残念な感じ。
1.n秒おきに実行する行を書き加えたcrontab(10s_cron)と、もとのままのcrontab(default_cron)をどこか(/home/tmin/cron)においておく。
$ ls -l /home/tmin/cron 10s_cron default_cron
2.rootのcronで予め用意したcronを指定時間に書き換え、指定時間に書き戻し。
50 21 * * * cp -p /home/tmin/cron/10s_cron /var/spool/cron/tmin 40 22 * * * cp -p /home/tmin/cron/default_cron /var/spool/cron/tmin 50 22 * * * cp -p /home/tmin/cron/10s_cron /var/spool/cron/tmin 40 23 * * * cp -p /home/tmin/cron/default_cron /var/spool/cron/tmin
結果的にうまく行きました!!
ちなみにrootのcronで/var/spool/cron/root自体を書き換えられるかは未検証。
よくよく考えたらsed置換とかでも良かったよね。
なんとなくもっとスマートなやり方はあるような気がします。