RubyでDSL書いてcronの設定ができるwheneverのコードリーディングをしました。バージョンは0.10.0です

まずはwheneverizeの処理ですが、以下のようにconfig/schedule.rbの設定ファイルを書き出しています

wheneverコマンドではOptionParserで引数パースしてからWhenever::CommandLine.executeを呼び出します

executeはWhenver::CommandLineをインスタンス化してから#runを呼び出します。

オプションを何も指定しないとWhenever.cronの戻り値を表示します

Whenever::JobListのコンストラクタではsetup.rbとconfig/schedule.rbをinstance_evalで評価します

例えば以下のようなコードの場合、everyとrunnerがそれぞれ評価されることになります

それぞれ以下のように定義されています

job_typeはsetup.rbで呼び出されており、command, rake, script, runnerが定義されています

各メソッド内で@jobsのハッシュにmailtoとcurrent_time_scope(everyの後の引数)をキーとしてWhenever::Jobのインスタンスをセットしています。

最後にWhenever::JobList#generate_cron_outputメソッドを呼び出します

環境変数はenvメソッドで定義でき、environment_variablesメソッドで出力されます

cron_jobsではeveryのブロック内でセットしたジョブをcronの設定に置き換えて出力します

cron_jobs_of_timeはWhenever::Output::Cron.outputを呼び出します

outputメソッドはprocess_templateによってoptionsのハッシュを使って@templateの文字列を置換します。job_templateのデフォルトは/bin/bash -l -c ':job'になるようにsetup.rbでセットされています。runnerでジョブを定義した場合、template変数はcd :path && :bundle_command :runner_command -e :environment ':task' :outputとなっています。これらのテンプレートの:xxxのバインド文字列を置換してcronの設定を出力しています。

標準出力のリダイレクションを指定している場合、options[:output]に値がセットされますが、このoutputはWhenever::Output::Redirectionのインスタンスが入ります。このクラスはto_sメソッドを実装していて、置き換え時に>> #{stdout}といったようなリダイレクトの文字列に置き換えられます。

最後に書き込みのオプションを指定している場合は、Whenever::CommandLine#write_crontabでcrontabのコマンドを使って設定しています。出力したcron設定を標準入力としてIO.popenのcrontabプロセスに食わせています