cron

提供: ArchWiki
ナビゲーションに移動 検索に移動

関連記事

Wikipedia より:

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

インストール

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

利用可能なパッケージ:

設定

有効化と自動起動

インストール後、デフォルトではデーモンは有効になりません。インストールされたパッケージは、systemctl で制御できるサービスを提供する可能性があります。たとえば、croniecronie.service を使用します。

/etc/cron.daily/ および同様のディレクトリをチェックして、どのジョブが存在するかを確認します。cron サービスを有効にすると、それらすべてがトリガーされます。

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

ジョブのエラーの対処

cron は、stdout および stderr からの出力を登録し、sendmail コマンドを介してユーザーのスプールに電子メールとして送信しようとします。/usr/bin/sendmail が見つからない場合、Cronie はメール出力を無効にします。メールがユーザーのスプールに書き込まれるためには、opensmtpd などの smtp デーモンがシステム上で実行されている必要があります。それ以外の場合は、sendmail コマンドを提供するパッケージをインストールして、リモートメールエクスチェンジャーにメールを送信するように設定できます。-m オプションを使用し、カスタムスクリプトを記述して、メッセージをログに記録することもできます。

ヒント: Postfix#ローカルメール を使用してローカルシステムユーザーに出力を送信できます。
  1. cronie.service ユニットを編集する。
  2. esmtpAUR, msmtp, opensmtpd, ssmtp をインストールする、もしくはカスタムスクリプトを書く。

ssmtp の例

ssmtp は送信だけを行う sendmail エミュレータで、ローカルコンピュータから smtp サーバーにメールを送信できます。活発なメンテナンスはされていませんが、設定済みのメールハブに対してメールを転送する方法としては最もシンプルです。デーモンを実行する必要はなく、設定ファイルを3行編集するだけで設定できます (認証されていないメールをメールハブでリレー出来る場合)。ssmtp はメールを受け取ったり、エイリアスを展開したり、キューを管理したりはしません。

ssmtpAUR をインストールしてください。/usr/bin/sendmail から /usr/bin/ssmtp にシンボリックリンクが作成されます。インストールしたら /etc/ssmtp/ssmtp.conf を編集してください。詳しくは ssmtp を参照。/usr/bin/sendmail に対してシンボリックリンクが作成されることで S-nail などのプログラム (/usr/bin/mail を提供するパッケージ) をそのまま使うことが可能です。

/usr/bin/sendmail がインストールされていることを認識されるために cronie を再起動してください。

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 の例

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

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

/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.adminschoice.com/crontab-quick-reference

基本的なコマンド

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 環境変数を定義します。

通常のユーザーとして、環境変数を正しく取得するには、sudo の代わりに su を使用する必要があります。

$ su -c "crontab -e"

su は新しいシェルで起動するため、この printf にエイリアスを設定するには、任意の文字列を運ぶ必要があります。

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

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

Cron は X.org サーバー下では実行されないため、X.org サーバーアプリケーションを実行するために必要な環境変数を知りません。そのため、環境変数を定義する必要があります。xuserrunAUR[リンク切れ: アーカイブ: aur-mirror] などのプログラムを使うことで 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

cronie に関連するファイル階層は次のとおりです。

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

Cronie は cronanacron の両方の機能を提供します。 cron は指定した時間にシステムが利用されている限り、一定時間間隔 (1分単位) でジョブを実行し、anacron は指定した時間にコマンドを実行します。 間隔を日数で指定する。 cron とは異なり、システムが継続的に稼働していることを前提としません。システムが起動するたびに、anacron は実行されるべきジョブがあるかどうかをチェックし、それに応じて処理します。

cron ジョブは、/etc/cron.d ディレクトリの crontab のようなファイルで定義するか、/etc/crontab ファイル内に追加できます。後者はデフォルトでは存在しませんが、存在する場合は使用されます。/etc/cron.d/0hourly の指示に従って、/etc/cron.hourly 内の実行可能ファイルは毎時間実行されます (デフォルトでは毎時1分) /etc/cron.minutely 内のファイルは、/etc/cron.d/0hourly で適切に指示されている場合、毎分実行されます。実行可能ファイルは通常、シェルスクリプトであり、実行可能ファイルへのシンボリックリンクも使用できます。

Anacron は、/etc/cron.daily/etc/cron.weekly、および /etc/cron.monthly} 内のファイルを実行することにより、同様に機能します。 ディレクトリは、目的のジョブ頻度に応じてそこに配置されます。cron ジョブ /etc/cron.hourly/0anacron は、保留中のタスクを実行するために anacron が 1日1回実行されるようにします。

ノート:
  • Cronie は run-parts を使って、異なるディレクトリのスクリプトを実行します。ファイル名にはドット (.) を含めてはいけません。なぜなら、デフォルトモードの run-parts はドットを黙って無視するからです (run-parts(8) 参照) 名前は大文字と小文字、数字、アンダースコア、マイナスハイフンのみで構成されている必要があります。
  • このような場合、systemctl status cronie の出力には CAN'T OPEN (/etc/crontab).No such file or digit というようなメッセージが表示されるかもしれません、しかし、これは cronie が必要としないので、無視することができます。
  • Cronie は /etc/cron.d/0hourly のパーミッションが重要です。もし /etc/cron.d/{hourly,weekly,daily} ...etc が破損していたり、不適切なパーミッションであれば、/etc/cron.d/0hourly のタスクは (アナクロンランチャーを含め) 実行されません。pacman -Qkk cronie はそのような問題があるかどうかを表示できます。
ヒント: 出力の送信を防ぎ、電子メールアラートを停止するには、各 cron ジョブの行末に >/dev/null 2>&1 を追加して、出力を /dev/null にリダイレクトします。
0 1 5 10 * /path/to/script.sh >/dev/null 2>&1
MAILTO=”” 変数を crontab ファイルに設定して、メールアラートを無効にすることもできます。

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 ページを見てください。

参照