日本だんでぃ協会
Japan Dandy Association

中の人プロフィール
だんでぃ
web拍手作った人
プログラマーでミュージシャンだと言い張って聞かない36才

おこんてんつ
  トップ
プログラミング (7)
デカ文字ジェネレータ
  音楽 (7)
  ポーカー (1)
  雑記 (1)

リンク
ろじっくぱらだいす
老舗のプログラム系テキストサイト。web拍手を思い付くきっかけをいただいたサイトです。ワタナベさんラヴ!

■cronで毎分以下の間隔に設定する時の注意点

2017/01/29 12:51 作成
みんな大好き、
crontab -e
って打とうとしたら、隣のキーを押しちゃって、
crontab -r
って打ってそのままエンターキーを押してパニックになる。で有名なcronですけど、
(-eは編集、-rは全削除になる。なんでそんなふうになってるの設計した人)

これって設定できる最小の間隔が「毎分」なんですよね。

手軽に設定できてとっても便利なcronなんですけど、
実行間隔を毎分以下、例えば5秒に1回実行したい。なんて時には使えません。

んで、なんとかならないものかと調べていたら、sleepコマンドを使う方法が色々なところで紹介されていました。
書き方はこんな感じです。
* * * * * for i in `seq 0 5 59`;do (sleep ${i}; 【実行したいコマンド】 ) & done;
「for i in `seq 0 5 59`;」らへんがなんか分かりづらいですけど、ようするに
* * * * * sleep  0; 【実行したいコマンド】
* * * * * sleep  5; 【実行したいコマンド】
* * * * * sleep 10; 【実行したいコマンド】
* * * * * sleep 15; 【実行したいコマンド】
* * * * * sleep 20; 【実行したいコマンド】
* * * * * sleep 25; 【実行したいコマンド】
* * * * * sleep 30; 【実行したいコマンド】
* * * * * sleep 35; 【実行したいコマンド】
* * * * * sleep 40; 【実行したいコマンド】
* * * * * sleep 45; 【実行したいコマンド】
* * * * * sleep 50; 【実行したいコマンド】
* * * * * sleep 55; 【実行したいコマンド】
と書きたいのをforループでスマートに記述しているわけですね。

設定された内容を意訳すると、

毎分、
「0秒待機してコマンドを実行」
「5秒待機してコマンドを実行」
「10秒待機してコマンドを実行」
「15秒待機してコマンドを実行」
「20秒待機してコマンドを実行」
「25秒待機してコマンドを実行」
「30秒待機してコマンドを実行」
「35秒待機してコマンドを実行」
「40秒待機してコマンドを実行」
「45秒待機してコマンドを実行」
「50秒待機してコマンドを実行」
「55秒待機してコマンドを実行」
を実行する。

という感じになります。

パッと見にはこれで設定できています。
ログを取ってみても期待通りに実行されていることが確認できます。

めでたしめでたし。

とはなりません。

この設定、どうやらサーバーに謎の負荷をかけるっぽいです。
どういうことかと言うと、こちらのグラフを見ていただきたいのですが、

これは、ある日のサーバーのロードアベレージのグラフなんですけど、
一定間隔で負荷が上がってますよね。

上記の「5秒ごとに実行するcron」を設定すると、この謎のロードアベレージの上昇が起きます。
しかも、このまま放置しておくと数ヶ月でサーバーがダウンします。

タチの悪いことに、ロードアベレージは上がっているのですが、
一般的にロードアベレージが上がる原因とされている、CPU、Disk I/O、スワップ辺りは全て正常で、
症状が現れるのが数時間置きという発見のしづらさで、
ロードアベレージのグラフを取っていなければ気付きませんでした。

このグラフの異常に気付いたのが、cronの設定をしてからだいぶ経ってからなので、
原因の特定に手間取ってしまったのですが、このcronの設定が悪さをしているのは間違いなさそうです。

ちなみに、やった検証は以下の感じです。
・シンプルに5秒間隔のcronを止めてみる。 → 直った
・5秒間隔じゃなくて10秒間隔にしてみる。 → グラフの山が低くはなるけど直らない
・実行していたPHPを「Hallo World」だけにして見る → 変化なし
・cronでsleepさせないで、PHPでsleepさせてみる → 変化なし
  (5秒sleep、10秒sleep、~55秒sleepさせてるPHPを毎分同時に計12個実行する)

などなど、いろいろやってみたのですが、理想的な落とし所は見つからず、
5秒毎に実行しなければいけなかったプログラムを毎分にしても大丈夫なように
アプリケーションの仕様を変更することで対応しました。

実際にこの方法で毎分以下のcronを設定している方や、
原因不明のサーバーダウンで困っている方のお役に立てたら幸いです。



前の記事 デカ文字コメントでコードを見やすくしよう!

2017 日本だんでぃ協会 All Rights Reserved.