WSLなどの開発用cronのcronrunを作った

概要

WSLなどで開発をしていると、定期実行をしたいポーリング系のコマンドがでてきたりします。cronなどシステム側の機能を利用していますとずーっとタスクが残り続けるので、単発で実行できるようなコマンドを作ってみました。

作成物

GitHub - tanakamasayuki/cronrun: Run crontab-style jobs or simple loops from the command line.
Run crontab-style jobs or simple loops from the command line. - tanakamasayuki/cronrun

上記のcronrunです。macosでも署名なしで動かせるようにpipxでの配布としました。

pipx install cronrun

上記にてコマンドが入ります。

cronrun "* * * * * echo hello"

できることは、crontabの1行を引数に渡して動かすことができます。上記だと毎分echoを実行しています。

cronrun --loop "date; sleep 2"

実行完了したら再実行するloopオプションもあります。ポーリング系のスクリプトの動作確認は上記が好ましいですが、多重実行の確認ができないので通常のcronタイプも実験したほうがよいと思います。

cronrun --log "* * * * * flock -n /tmp/worker.lock sleep 90"

同時起動を防ぐにはflockなどを使うのが多いと思いますが、結構動作確認が面倒です。

faketimeを使って加速実験

sudo apt install faketime

上記でfaketimeをいれると、時刻の操作をして動作実験できるようになります。

faketime -f "+0 x60" cronrun --log "* * * * * flock -n /tmp/worker.lock sleep 90"

たとえば-fオプションを使うと現在からの相対指定が+0なので、現時刻からスタートして、x60なので60倍で時間が進みます。上記だと1秒あたり1分進む設定でcronrunを実行しています。

flockの同時起動制御が動くとすぐに実行が完了するのでlogなどを確認をして多重実行がブロックされているのを確認可能です。

faketime -f "+0 x60" cronrun "2-59/5 * * * * date"

たとえば上記のようなちょっと特殊な指定をした場合の確認とかがしやすいです。

$ faketime -f "+0 x600" cronrun "2-59/5 * * * * date"
Sun Mar  8 13:27:02 JST 2026
Sun Mar  8 13:32:04 JST 2026
Sun Mar  8 13:37:04 JST 2026
Sun Mar  8 13:42:05 JST 2026
Sun Mar  8 13:47:03 JST 2026
Sun Mar  8 13:52:04 JST 2026
Sun Mar  8 13:57:04 JST 2026
Sun Mar  8 14:02:03 JST 2026
Sun Mar  8 14:07:02 JST 2026
Sun Mar  8 14:12:02 JST 2026
Sun Mar  8 14:17:05 JST 2026
Sun Mar  8 14:22:04 JST 2026
Sun Mar  8 14:27:04 JST 2026
Sun Mar  8 14:32:02 JST 2026

上記だと2分、7分、12分と5分間隔で起動する指定ですね。cronの時間指定の確認のも利用可能に作っています。

WSLで時間がずれる場合

私の環境の場合WSLだとWindowsと15秒程度時間が遅れてズレていました。そして、たまにWindowsの時間に同期して、さらにまた15秒遅れるみたいなループがあり時間が安定していませんでした。

いろいろ試したところ、Hyper-Vを利用している場合にはWindows Timeのサービスを常時起動したほうがよいみたいです。

>sc.exe qc w32time
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: w32time
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\WINDOWS\system32\svchost.exe -k LocalService
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Windows Time
        DEPENDENCIES       :
        SERVICE_START_NAME : NT AUTHORITY\LocalService

w32timeがWindows Timeのサービスになります。START_TYPEが標準は3 DEMAND_STARTの手動実行なので、定期的に実行されてWindowの時間は調整されるのですが、Hyper-V側の時間はズレたままみたいです。

上記のサービスを手動から自動に変更することでWSLの時間が安定して動くようになりました。

sc.exe config w32time start= auto

コマンドだと上記で設定できますが、管理者権限でコンソールを開く必要があります。

まとめ

Linuxとmacosを両方サポートするとなるとpipxで配布するのが良さそうです。いろいろAIと壁打ちしたのですが、goとかを推奨してくるのですがバイナリをコピーするだけですというのですが、バイナリを手動でコピーしてくないですし、installコマンドとかも使いたくないですし、CPUの種類に合わせるためにinstall.shを実行とかも嫌です。

そうなるとpipxが環境依存が少なくて、パッケージマネージャー経由で気軽に配布できる環境になると思います。

そして、WSLで時間がズレていくのは最近気になっていたので解決してよかったです。実行時間のログを取っていて、経過時間がマイナスになるのでかなり不便でした。一般的なWSL環境だとあまり起こらないかもしれませんが、Hyper-Vも一緒に入れているのでWindowsとHyper-Vの時間管理が二重に干渉してWSLに悪影響を与えていた可能性があります。

コメント