cron

提供: ArchWiki
2016年9月23日 (金) 21:05時点におけるKusakata (トーク | 投稿記録)による版 (翻訳)
ナビゲーションに移動 検索に移動

関連記事

Wikipedia より:

cron は Unix ライクなコンピュータオペレーティングシステムにおける時間基準のジョブスケジューラです。cron を使うことでジョブ (コマンドやシェルスクリプト) をスケジュールして定期的に特定の時刻・時間に実行することが可能になります。システムのメンテナンスや管理を自動化するためによく使われます。

インストール

cron の実装はたくさん存在しますが、デフォルトではそのいずれもインストールされません。代わりにベースシステムは systemd/タイマー を使用しています。実装の比較については Gentoo の cron ガイド を見て下さい。

公式リポジトリにあるパッケージ:

AUR にあるパッケージ:

設定

有効化と自動起動

デーモンをインストールしても、デフォルトでは有効になっていません。インストールしたパッケージにはサービスが入っているので、systemctl を使用してコントロールすることができます。例えば、cronie を起動して有効化するには:

# systemctl start cronie
# systemctl enable cronie

これらのコマンドはあなたが選んだ実装に合わせて変更してください、例えば:

# systemctl start dcron
# systemctl enable dcron

/etc/cron.daily/ や同じようなディレクトリを見てジョブが存在するか確認してください。cron サービスを有効にすることで、それらのジョブが作動します。

ノート: cronie には他のジョブの実行を遅延させるための、0anacron hourly ジョブが存在します。例えばコンピュータの電源を切った場合の標準実行の時があたります。

ジョブのエラーの対処

cron は stdoutstderr からの出力を記録して sendmail コマンドを使ってユーザーのスプールにメールで送信しようと試みます。/usr/bin/sendmail が存在しない場合 Cronie はメール出力を無効化します。これらのメッセージをログとして記録するには -m オプションを使ってスクリプトを書くか基本的な SMTP サブシステムをインストールしてください。

  1. cronie.service ユニットを編集する。
  2. esmtp, msmtp, opensmtpd をインストールする、もしくはカスタムスクリプトを書く。

msmtp の例

msmtp を使って cronie からメールを取得する方法は2つあります:

  1. msmtp-mta パッケージをインストールします。/usr/bin/sendmail から /usr/bin/msmtp にシンボリックリンクが作成されます。cronie を再起動して新しい sendmail コマンドが検出されていることを確認してください。msmtp にユーザー名をメールアドレスに変換する手段を用意する必要があります。
    • 次のように crontab に MAILTO 行を追加する:
      MAILTO=your@email.com
      または:
    • /etc/msmtprc に次の行を加えて:
      aliases /etc/aliases
      /etc/aliases を作成してください:
      your_username: your@email.com
      # Optional:
      default: your@email.com
  2. cronie.service ユニットを編集します。例えば、/etc/systemd/system/cronie.service.d/msmtp.conf を作成してください:
    [Service]
    ExecStart=
    ExecStart=/usr/bin/crond -n -m '/usr/bin/msmtp -t'
ノート: ExecStart= を空にすると前に指定された ExecStart コマンドが全てキャンセルされます。

esmtp の例

esmtpprocmail をインストールしてください。

インストールした後、ルーティングを設定してください:

/etc/esmtprc
identity myself@myisp.com
       hostname mail.myisp.com:25
       username "myself"
       password "secret"
       starttls enabled
       default
mda "/usr/bin/procmail -d%T"

Procmail は配送モードで動作するのに root 権限を必要としますが cronjob を root で実行している場合は問題になりません。

正しく動作しているかテストするには、ファイル message.txt を作成して中に "test message" を記述してください。

同じディレクトリから次を実行してください:

$ sendmail user_name < message.txt 

そして:

$ cat /var/spool/mail/user_name

テストメッセージと送信された日時が表示されるはずです。

全てのジョブのエラー出力は /var/spool/mail/user_name にリダイレクトされます。

権限の問題で、root にメールを作成・送信するのは困難です (例: su -c "")。esmtp の設定で root のメールを全て通常のユーザーに転送させることができます:

/etc/esmtprc
force_mda="user-name"
ノート: 上記のテストが上手く行かない場合、同じ内容で ~/.esmtprc にローカルの設定を作成してみて下さい。

適切なパーミッションにするために次のコマンドを実行してください:

$ chmod 710 ~/.esmtprc
それから message.txt でまたテストしてください。

opensmtpd の例

opensmtpd をインストールしてください。

/etc/smtpd/smtpd.conf を編集します。以下の設定でローカル配信が可能になります:

listen on localhost
accept for local deliver to mbox

次のコマンドでテストが行えます:

# systemctl start smtpd
$ echo test | sendmail user

user は mbox フォーマットを扱えるメールクライアントを使うか、/var/spool/mail/user ファイルを見ることでメールを確認できます。全てが問題なく動作するようでしたら、opensmtpd を有効にします:

# systemctl enable smtpd

この方法には、リモートサーバーに cron のローカルな通知が送信しないという利点があります。ネットワーク接続も必要ありません。欠点としては、新しいデーモンを実行する必要があります。

ノート:
  • 執筆時点では Arch の opensmtpd パッケージは /var/spool/mail/user 下に必要なディレクトリを全て作成しません。ただし、デーモンが必要な所有者とパーミッションについて警告を出すので、それに従ってディレクトリを作成してください。
  • 上記の設定はリモート接続を受け入れませんが、用心として iptables などを使ってセキュリティレイヤーでポート25をブロックするのも良いでしょう。

長い cron ジョブ

仮に cron によって以下のプログラムが実行されると:

#!/bin/sh
echo "I had a recoverable error!"
sleep 1h

以下のことが起こります:

  1. cron がスクリプトを実行
  2. 出力があったらすぐに、cron は MTA を実行し、MTA にヘッダーをわたす。ジョブは完了しておらず、出力がまだあるかもしれないので、パイプは開きっぱなしになる。
  3. MTA は postfix との接続を開いて、残りのボディが来るまで待っている間、接続を開き続ける。
  4. 一時間以内に postfix はアイドル状態の接続を閉じて、以下のようなエラーを表示する:
smtpmsg='421 … Error: timeout exceeded' errormsg='the server did not accept the mail'

moreutils の chronic または sponge コマンドを使うことでこの問題は解決できます。それぞれの man ページより:

chronic
chronic はコマンドを実行して、コマンドが失敗した場合にのみ (0以外の終了コードが吐かれたりクラッシュしたとき)、標準出力や標準エラーが表示されるようにします。コマンドが問題なく実行されたときは、何も出力されません。
sponge
sponge は標準入力を読み込んで指定されたファイルに書き出します。シェルのリダイレクトと違って、sponge は出力ファイルを開く前のあらゆる入力を吸い上げてしまいます。出力ファイルが指定されなかったときは、sponge は標準出力に出力します。

マニュアルには載っていませんが、chronic は標準出力を開く前のコマンド出力をバッファします (sponge も同じようにバッファを使います)。

Crontab のフォーマット

crontab の基本的なフォーマットは:

minute hour day_of_month month day_of_week command
  • minute は 0 から 59 までの値。
  • hour は 0 から 23 までの値。
  • day_of_month は 1 から 31 までの値。
  • month は 1 から 12 までの値。
  • day_of_week は 0 から 6 までの値、0 が日曜日。

カンマを使うことで複数の時間を指定することが出来ます。時間の範囲はハイフンで決めることができ、アスタリスクはワイルドカード文字になります。スペースはフィールドを分けるのに使います。例えば、次の行はスクリプト i_love_cron.sh を夏の期間 (6月, 7月, 8月) を除く平日の午前9時から午後4:55まで5分間隔で実行します:

*/5 9-16 * 1-5,9-12 1-5 ~/bin/i_love_cron.sh

さらに、crontab には特殊なキーワードもいくつか存在します:

@reboot : 起動時
@yearly : 一年毎
@annually ( == @yearly)
@monthly : 一月毎
@weekly : 一周毎
@daily : 一日毎
@midnight ( == @daily)
@hourly : 一時間毎

例えば、起動時に i_love_cron.sh を実行する場合:

@reboot ~/bin/i_love_cron.sh

参照: http://www.linuxandlife.com/2013/01/how-to-use-crontab-to-schedule-tasks.html#sthash.AXvOdsAz.dpuf

基本的なコマンド

Crontab を直接編集してはいけません。代わりに、ユーザーは crontab プログラムを使って crontab を編集してください。このコマンドを実行するには、ユーザーは users グループのメンバーである必要があります (gpasswd コマンドを見て下さい)。

crontab を一覧するには、次のコマンドを実行してください:

$ crontab -l

crontab を編集するには、次のコマンドを使って下さい:

$ crontab -e
ノート: デフォルトでは crontab コマンドは vi エディタを使います。使用するエディタを変えたいときは、EDITOR または VISUALexport するか、直接エディタを指定してください: EDITOR=vim crontab -e

crontab を削除するには、次のコマンドを使って下さい:

$ crontab -r

既に crontab が存在していて、古い crontab を完全に上書きするには次を使って下さい:

$ crontab saved_crontab_filename

コマンドライン (Wikipedia:ja:標準ストリーム) から crontab を上書きするには:

$ crontab - 

他の誰かの crontab を編集するには、次のコマンドを root で実行してください:

# crontab -u username -e

同じフォーマット (コマンドに -u username を追加すること) は crontab の表示・削除にも使えます。

サンプル

コマンド /bin/echo Hello, world! を毎月の毎日の毎時間の1分目 (つまり 12:01, 1:01, 2:01 ...) に実行するエントリ:

01 * * * * /bin/echo Hello, world!

1月の平日に5分ごと (つまり 12:00, 12:05, 12:10 ...) に同じジョブを実行するエントリ:

*/5 * * jan mon-fri /bin/echo Hello, world!

次の行は夏 (6月, 7月, 8月) 以外の毎月の平日 (月-金) の午前9時から午後5時まで5分間隔で (午後5時0分は除く) スクリプト i_love_cron.sh を実行します ("man 5 crontab" より):

*0,*5 9-16 * 1-5,9-12 1-5 /home/user/bin/i_love_cron.sh

定期的な設定は次の crontab テンプレートのように入力することも可能です:

# Chronological table of program loadings                                       
# Edit with "crontab" for proper functionality, "man 5 crontab" for formatting
# User: johndoe

# mm  hh  DD  MM  W /path/progam [--option]...  ( W = weekday: 0-6 [Sun=0] )
  21  01  *   *   * /usr/bin/systemctl hibernate
  @weekly           $HOME/.local/bin/trash-empty

デフォルトエディタ

デフォルトエディタを変更するには、シェルの初期化スクリプトで EDITOR 環境変数を定義してください (vim ユーザーは vim-default-editorAUR が使えます)。例:

/etc/profile.d/nano-default-editor.sh
#!/bin/sh

export EDITOR=/usr/bin/nano

環境変数が正しく使われるようにするために、通常ユーザーでは、sudo の代わりに su を使う必要があります:

$ su -c "crontab -e"

上記のコマンドをエイリアスにするときは printf が必要です。su を使うと新しいシェルが起動するためです:

alias scron="su -c $(printf "%q " "crontab -e")"

run-parts 問題

cronie は run-parts を使用して cron.daily/cron.weekly/cron.monthly のスクリプトを実行します。それらのスクリプトの名前にはドット (.) を含められないので注意してください (例: backup.sh)。オプションを付けないと run-parts がスクリプトを無視してしまうためです (参照: man run-parts)。

X.org サーバーを使用するアプリケーションを実行

Cron は X.org サーバー下では実行されないため、X.org サーバーアプリケーションを実行するために必要な環境変数を知りません。そのため、環境変数を定義する必要があります。xuserrunAUR などのプログラムを使うことで X.org アプリケーションを実行できます:

17 02 * ... /usr/bin/xuserrun /usr/bin/xclock

もしくは環境変数を手動で定義する方法もあります (echo $DISPLAY で現在の DISPLAY の値がわかります):

17 02 * ... env DISPLAY=:0 /usr/bin/xclock

SSH などを通す場合は、権限を与えてください:

# xhost +si:localuser:$(whoami)

非同期のジョブ処理

コンピュータをオフにしてもジョブがちゃんと実行されるようにしたい場合、複数の解決方法が存在します (簡単な順番で並んでいます):

Cronie

Cronie には anacron が含まれています。プロジェクトのホームページより:

Cronie には特定時刻に指定したプログラムを起動するための標準 UNIX デーモンである crond と関連ツールが含まれています。Cronie はオリジナルの cron をベースとしており、pam や SELinux を利用できるようにするなどの改善がされています。

ノート: systemctl status cronie の出力に crond[<PID>]: (root) CAN'T OPEN (/etc/crontab): No such file or directory のようなメッセージが表示される場合がありますが、cronie 1.4.8 現在、これはエラーではありません。こちら を参照。

Dcron

dcronAUR は標準で非同期のジョブ処理をサポートしています。以下のようにジョブの名前に @hourly, @daily, @weekly, @monthly を付けて下さい:

@hourly         ID=greatest_ever_job      echo This job is very useful.

Cronwhip

cronwhipAUR は見過ごされた cron ジョブを自動的に実行するスクリプトです。昔 Arch でデフォルトの cron 実装だった dcron で動作します。フォーラムスレッド も参照。

Anacron

Anacron はジョブを非同期に処理する dcron を完全に置き換えます。

Anacron は cronie に含まれており、設定ファイルは /etc/anacrontab です。フォーマットの情報は anacrontab(5) man ページにあります。anacron -T を実行することで /etc/anacrontab に問題がないかテストすることができます。

Fcron

anacron と同じように、fcron はコンピュータの電源が落ちている場合を想定しますが、anacron とは違って、一日よりも短いインターバルでイベントを組むことができます。定期的にサスペンド・ハイバネートを行うような環境 (ノートパソコンなど) で有用です。cronwhip と同様に、fcron はコンピュータが落ちている間に実行すべきだったジョブを実行します。

cronie を fcron で置き換える場合、spool ディレクトリが /var/spool/fcron になり、ユーザーの crontab を編集するときに crontab の代わりに fcrontab コマンドを使うことになるので注意してください。crontab はバイナリ形式で保存され、spool ディレクトリに foo.orig という名前のテキストファイルが出来ます。手動でユーザーの crontab を編集するスクリプトを使っているのであれば、修正が必要です。

伝統的なユーザーの crontab を fcron 方式に変換するクイックスクリプトレット:

cd /var/spool/cron && (
 for ctab in *; do
  fcrontab ${ctab} -u ${ctab}
 done
)

フォーラムスレッド も参照。

排他性の確保

ジョブの実行時間が長くなる可能性がある場合 (例えばシステムのバックアップは変更箇所が多かったりネットワーク接続が遅かったりして長くなることがあります)、flock (util-linux) を使うことで cron ジョブが二重に実行されないようにすることができます。

5,35 * * * * /usr/bin/flock -n /tmp/lock.backup /root/make-backup.sh

cronie

vixie-cron (伝統的な cron) をずっと使っていた場合 cronie の設定方法に困惑させられるかもしれません。ファイル階層は以下のとおりになっています:

   /etc
     |----- anacrontab
     |----- cron.d
              | ----- 0hourly
     |----- cron.daily
     |----- cron.deny
     |----- cron.hourly
     |----- cron.monthly
     |----- cron.weekly
     |----- crontab

crontab ファイルはデフォルトでは作成されませんが、追加されたジョブは実行されます。Cronie は cron と anacron の両方の機能を提供します。マシンの時刻が指定した日時になったときに cron は特定の間隔 (精度は1分まで) でジョブを実行するのに対して、anacron は特定日時にマシンの電源が入っているかどうか関係なくジョブを実行します (精度は最低1日)。マシンの電源が入ると、anacron は実行しておくべきジョブがないかどうか確認して、あれば実行します。/etc/cron.d/etc/cron.hourly ディレクトリは cron 機能で使用し、/etc/anacrontab ファイルと /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly ディレクトリは anacron 機能で使用します。/etc/cron.deny ファイルは特にジョブの作成を禁止されていないユーザーが cron ジョブを作成することができます。

システム全体の cron ジョブを作りたい場合、crontab のようなファイルを作成して /etc/cron.d ディレクトリに配置するか /etc/crontab にジョブを追加してください。/etc/cron.hourly に存在する実行可能ファイル (普通は全てシェルスクリプト) は毎時間実行されます。

Anacron 機能も同じように実装されていますが、使用するのは /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly ディレクトリで、ジョブを実行する間隔で決めます。anacron のジョブファイルも実行可能ファイルです。crontab フォーマットではありません。Anacron は毎時間 crontab ファイルの /etc/cron.d/0hourly によって /etc/cron.hourly の中にある /etc/cron.hourly/0anacron ファイルから実行されます。ファイルを削除すると anacron が実行されなくなります。

Dcron

cron デーモンは crontab という名前の設定ファイルをパースします。各ユーザーは別々の crontab ファイルを使うことで別個にコマンドを実行することができます。root ユーザーの crontab はシステム全体のコマンドのスケジュールを組みために使います (cron の実装によっては、ユーザーが /etc/crontab/etc/cron.d ディレクトリを使うことができる場合もあります)。

/var/spool/cron/root
# Run command at a scheduled time
# Edit this 'crontab -e' for error checking, man 1 crontab for acceptable format

# <@freq>                       <tags and command>
@hourly         ID=sys-hourly   /usr/sbin/run-cron /etc/cron.hourly
@daily          ID=sys-daily    /usr/sbin/run-cron /etc/cron.daily
@weekly         ID=sys-weekly   /usr/sbin/run-cron /etc/cron.weekly
@monthly        ID=sys-monthly  /usr/sbin/run-cron /etc/cron.monthly

# mm  hh  DD  MM  W /path/command (or tags) # W = week: 0-6, Sun=0
  21  01  *   *   * /usr/bin/systemctl suspend

以下の行は crontab エントリのフォーマットの例です。空白で区切られたフィールドに以下を指定します:

  1. @period
  2. ID=jobname (this tag is specific to dcron)
  3. command

crontab エントリの他の標準フォーマット:

  1. minute
  2. hour
  3. day
  4. month
  5. day of week
  6. command

crontab ファイルは通常 /var/spool/cron/username に保存され、root の crontab ファイルは /var/spool/cron/root になります。

詳しい情報や設定例は crontab の man ページを見てください。

参照