Crontabとは
Cronは、Unix系システム上でタスクをスケジュールするためのソフトウェアユーティリティです。名前はギリシャ語で「時間」を意味する “Chronos “に由来します。
Cronのタスクは、実行されるコマンドを含むテキストファイルであるcrontabで定義されます。crontabで使用される構文については、本記事で後述します。
Pythonは、Cronでスケジュールされたジョブを管理するためのcrontabモジュールを提供しています。このモジュールは、Cronへのアクセス、ジョブの作成、制限の設定、ジョブの削除など、様々な機能を提供します。この記事では、これらの操作をyhour Pythonのコードの中でどのように使用するかを紹介します。
興味のある読者のために、公式のヘルプページは https://pypi.python.org/pypi/python-crontab で見ることができます。
Crontabの構文
Cronは、タイムスケジュールを定義するために特定の構文を使用します。これは、空白で区切られた5つのフィールドから構成されています。フィールドは以下の通りです。
Minute Hour Day Month Day_of_the_Week
フィールドは以下の値を持つことができます。
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
│ │ │ │ │ 7 is also Sunday on some systems)
│ │ │ │ │
│ │ │ │ │
* * * * * command to execute
出典 ウィキペディア Cron. https://en.wikipedia.org/wiki/Cron で利用可能です。
Cronは特殊文字も使えるので、より複雑なタイムスケジュールを作成することができます。特殊文字は以下のような意味を持っています。
| 文字|意味
| カンマ|複数の値を区切る
| ハイフン| 値の範囲を示す| アスタリスク| すべての値を示す
| アスタリスク|取り得るすべての値を示す。
| フォワードスラッシュ|EVERY|を表す。
それでは、いくつかの例を見てみましょう。
-
- 「 * *」は、「毎月、毎月、毎月、毎週、毎正時、毎正月、毎正月、毎正月、毎正月、毎正月、毎正月」を意味します。
-
-
0 16 1,10,22 *
は、毎月1日、10日、22日の午後4時(16時間目)にタスクを実行するようcronに指示します。
-
Crontabのインストール
CrontabはPythonの標準的なインストールには含まれていません。したがって、最初にしなければならないことは、これをインストールすることです。
これは pip
コマンドで行います。唯一考慮しなければならないのは、モジュールの名前が ‘crontab’ だけではなく ‘python-crontab’ であることです。次のコマンドは、私たちのマシンにパッケージをインストールします。
$ pip install python-crontab
Crontabへのアクセス方法
crontabのヘルプによると、cronにジョブを含めるには5つの方法があります。そのうち3つはLinuxのみで動作し、2つはWindowsでも使用可能です。
cronにアクセスする最初の方法は、ユーザー名を使用する方法です。構文は以下の通りです。
cron = CronTab(user='username')
他の2つのLinuxの方法は、次のとおりです。
cron = CronTab()
# or
cron = CronTab(user=True)
Windowsでも動作するシンタックスがあと2つある。
最初の方法では、「filename.tab」というファイルに定義されているタスクを呼び出す。
cron = CronTab(tabfile='filename.tab')
2つ目は、cronのシンタックスに従ってタスクを定義するものである。
cron = CronTab(tab="""* * * * * command""")
新しいジョブの作成
cronにアクセスしたら、次のコマンドを使用して新しいタスクを作成します。
cron.new(command='my command')
ここで、my command
はコマンドラインから実行されるタスクを定義します。
また、タスクにコメントを追加することもできます。そのシンタックスは以下の通りです。
cron.new(command='my command', comment='my comment')
例で見てみましょう。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py')
job.minute.every(1)
cron.write()
上記のコードでは、まずユーザー名でcronにアクセスし、example1.pyというPythonスクリプトを実行するジョブを作成しました。さらに、このタスクは1分ごとに実行されるように設定しました。write()` 関数は cron に私たちのジョブを追加します。
example1.py スクリプトは以下の通りです。
from datetime import datetime
myFile = open('append.txt', 'a')
myFile.write('
Accessed on ' + str(datetime.now()))
上記のコードからわかるように、プログラムは “Accessed on “というフレーズを開き、アクセス日時を追加していきます。
結果は以下のようになります。
図1
予想通り、Figure 1はファイルがプログラムによってアクセスされたことを示している。example1.py プログラムが cron で実行されている間、このプログラムは割り当てられたタスクを実行しつづけます。
いったん cron がアクセスされると、複数のジョブを追加することができます。例えば、上記の例の次の行は、cronによって管理される2つ目のタスクを追加します。
job2 = cron.new(command='python example2.py')
新しいタスクが追加されたら、それぞれのタスクに制限を設定することができます。
設定制限
Pythonのcrontabモジュールを使用する主な利点の1つは、cronの構文を使用せずに時間制限を設定することができることです。
上記の例では、1分ごとにジョブを実行するように設定する方法をすでに見ました。その構文は以下の通りです。
job.minute.every(minutes)
同じように、時間を設定することもできます。
job.hour.every(hours)
また、特定の曜日にタスクを実行するように設定することもできます。例えば
job.dow.on('SUN')
上記のコードは日曜日にタスクを実行するようにcronに指示し、次のコードは日曜日と金曜日にタスクをスケジュールするようにcronに指示します。
job.dow.on('SUN', 'FRI')
同様に、特定の月にタスクを実行するようにcronに指示することもできます。例えば
job.month.during('APR', 'NOV')
これは、4月と11月にプログラムを実行するようにcronに伝えます。
考慮すべき重要なことは、時間制限を設定するたびに、前の制限を無効にすることです。したがって、例えば
job.hour.every(5)
job.hour.every(7)
上記のコードは、最終的なスケジュールを7時間ごとに実行するように設定し、以前の5時間のスケジュールをキャンセルします。
ただし、次のように以前のスケジュールに追加する場合は別です。
job.hour.every(15)
job.hour.also.on(3)
この場合、スケジュールは15時間ごと、そして午前3時に設定される。
この「毎」という条件は少しわかりにくいかもしれません。もし、job.hour.every(15)
と書けば、* */15 * *
と同じ意味になります。見てわかるように、分数は変更されていません。
もし、分フィールドをゼロにしたい場合は、次の構文を使用します。
job.every(15).hours()
これにより、スケジュールは0 */4 * * *
に設定されます。同様に、「曜日」、「月」、「曜日」フィールドについても同様です。
例を挙げます。
-
-
job.every(2).month
は0 0 */2 *
に相当し、job.month.every(2)
は* * */2 *
に相当する。
-
-
job.every(2).dows
は0 0 * */2
と同等、job.dows.every(2)
は* * */2
と同等です。
以下の例で、その違いを確認することができます。
from crontab import CronTab
cron = CronTab(user='username')
job1 = cron.new(command='python example1.py')
job1.hour.every(2)
job2 = cron.new(command='python example1.py')
job2.every(2).hours()
for item in cron:
print item
cron.write()
プログラムを実行した結果、以下のようになります。
$ python cron2.py
* */2 * * * python /home/eca/cron/example1.py
0 */2 * * * python /home/eca/cron/example1.py
$
図2
Figure 2でわかるように、このプログラムは2番目のタスクの分をゼロに設定し、1番目のタスクの分をデフォルト値に定義している。
最後に、マシンを起動するたびにタスクが実行されるように設定することができます。その構文は以下の通りである。
job.every_reboot()
クリアランスの制限
以下のコマンドで、タスクの制限をすべて解除することができます。
job.clear()
次のコードは、上記のコマンドを使用する方法を示しています。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py', comment='comment')
job.minute.every(5)
for item in cron:
print item
job.clear()
for item in cron:
print item
cron.write()
このコードを実行すると、次のような結果が得られます。
$ python cron3.py
*/5 * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment
図3
図3からわかるように、スケジュールが5分ごとからデフォルトの設定に変更されていることがわかります。
ジョブの有効化・無効化
タスクは、以下のコマンドを使用して有効化または無効化することができます。
ジョブを有効にするには
job.enable()
ジョブを無効にするには
job.enable(False)
タスクが有効か無効かを確認するために、次のコマンドを使用します。
job.is_enabled()
次の例は、以前に作成されたジョブを有効化および無効化し、両方の状態を確認する方法を示しています。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py', comment='comment')
job.minute.every(1)
cron.write()
print job.enable()
print job.enable(False)
結果は次のようになります。
$ python cron4.py
True
False
図4
有効性の確認
タスクが有効かどうかは、以下のコマンドで簡単に確認することができます。
job.is_valid()
次の例は、このコマンドを使用する方法を示しています。
コード偽
上記のプログラムを実行すると、次の図のようにバリデーションが行われます。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py', comment='comment')
job.minute.every(1)
cron.write()
print job.is_valid()
図5
Cronの全ジョブ一覧
無効なジョブを含むすべてのcronジョブは、以下のコードでリストアップできます。
$ python cron5.py
True
このコードを最初の例に追加すると、次のように画面に表示され、我々のタスクが示されます。
for job in cron:
print job
図6
仕事探し
Pythonのcrontabモジュールでは、コマンド、コメント、スケジュールされた時間などの選択基準に基づいてタスクを検索することもできます。それぞれのケースで構文が異なります。
コマンドにしたがって検索する
$ python cron6.py
* * * * * python /home/eca/cron/example1.py
ここで、’command name’ は、サブマッチまたは正規表現である。
コメントによる検索
cron.find_command("command name")
時間から探す
cron.find_comment("comment")
次の例は、先に述べた3つの基準に従って、以前に定義されたタスクを見つける方法を示しています。
cron.find_time(time schedule)
結果は、同じ仕事が3回リストアップされます。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py', comment='comment')
job.minute.every(1)
cron.write()
iter1 = cron.find_command('exam')
iter2 = cron.find_comment('comment')
iter3 = cron.find_time("*/1 * * * *")
for item1 in iter1:
print item1
for item2 in iter2:
print item2
for item3 in iter3:
print item3
図7
見ての通り、毎回正しくcronコマンドを見つけることができます。
ジョブの削除
各ジョブは個別に削除することができます。構文は次のとおりです。
$ python cron7.py
* * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment
次のコードは、以前に作成されたタスクを削除する方法を示しています。このプログラムでは、まずタスクを作成します。次に、すべてのタスクをリストアップし、先ほど作成したものを表示します。その後、タスクを削除し、空のリストを表示します。
cron.remove(job)
結果は次のようになります。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py')
job.minute.every(1)
cron.write()
print "Job created"
# list all cron jobs (including disabled ones)
for job in cron:
print job
cron.remove(job)
print "Job removed"
# list all cron jobs (including disabled ones)
for job in cron:
print job
図8
ジョブは、条件に基づいて削除することもできます。例えば
$ python cron8.py
Job created
* * * * * python /home/eca/cron/example1.py
Job removed
この場合、comment='my comment'
に該当するジョブはすべて削除されます。
全職種クリア
以下のコマンドで、すべてのcronジョブを一度に削除することができます。
cron.remove_all(comment='my comment')
次の例は、すべてのcronジョブを削除し、空のリストを表示します。
cron.remove_all()
環境変数
スケジュールされたタスクに固有の環境変数を定義し、画面に表示することもできます。変数は辞書に保存されます。新しい環境変数を定義するためのシンタックスは以下の通りです。
from crontab import CronTab
cron = CronTab(user='username')
cron.remove_all()
# list all cron jobs (including disabled ones)
for job in cron:
print job
すべての環境変数の値を取得したい場合は、次のシンタックスを使用します。
job.env['VARIABLE_NAME'] = 'Value'
以下の例では、タスク「user」に対して2つの新しい環境変数を定義し、その値を画面上に表示している。コードは以下の通りである。
job.env
上記のプログラムを実行すると、次のような結果が得られる。
from crontab import CronTab
cron = CronTab(user='username')
job = cron.new(command='python example1.py')
job.minute.every(1)
job.env['MY_ENV1'] = 'A'
job.env['MY_ENV2'] = 'B'
cron.write()
print job.env
図9
また、Cronレベルの環境変数は’cron.env’に格納される。
まとめ
Pythonモジュールcrontabは、Unix系システムで利用可能なcronアプリケーションをプログラム的に管理するための便利なツールを提供してくれます。これを使うことで、crontabを作ることに頼るのではなく、Pythonのコードを使って頻繁に発生するタスクを管理することができるのです。
このモジュールはかなり完成度が高いです。その動作についてはいくつかの批判がありますが、cronに接続し、スケジュールされたタスクを作成し、それらを管理するための関数が含まれています。上記の例で示したように、その使い方は極めて直接的である。このように、Pythonの主な特徴である「シンプルさ」で複雑なスクリプトを可能にするツールを提供しています。