Wednesday, 13 October, 2021 UTC


Summary

この記事はTwilio Developer EvangelistのNathaniel Okenwaがこちら(英語)で執筆した記事を日本語化したものです。
JavaScriptを使用して定期的なタスクを実行したことがあるでしょうか? 私は常に、反復タスクを自動化する方法を模索しています。多くの単調な作業をする心理的な負担を和らげるためにも、コードの力が大変役立ちます。多くのアプリケーションは、管理、システムメンテナンス、毎日のバックアップからメールを初めとするメッセージの送信など、重要なタスクを定期的に実行する必要もあります。そこでcronの出番です!
Cron式
Cronを使用してジョブの実行時間をスケジュールし、決めた日時に自動で実行できます。Cron式は、タスクの実行スケジュールを定義する文字列です。こちらのリンクを参考にしてCron式を作成できます。例えば、Node.jsスクリプトを毎朝9時に実行するとしましょう。そのcron式は次のようになります。
0 0 9 * * * [command]
それぞれのパートごとに見てみましょう。式の(最初を除く)の5つの部分は、分、時、日付、月、曜日に対応する文字列で構成されます。時間単位xで毎回コマンドを実行するには、その部分に*を記入します。上記のcron式では、0分、9時、毎日、毎月、全曜日にコマンドが実行されることになります。
間隔をおいてコマンドを実行するには、/を使用します。例えば、1日おきの正午にコマンドを実行するのであれば、次のような式になります。
0 0 12 1/2 * * [command]
Cron式を理解したところで、毎日のメッセージ送信に使用できる4つの方法を見てみましょう。
Crontabのローカル実行

UNIXシステム

crontabはUNIX(ファミリー)オペレーティングシステムに組み込まれたソフトウェアユーティリティです。一連のジョブリストがcrontabファイルに格納されます。UNIXベースのOS(Linux、MacOSなど)では、次のコマンドによりcrontabファイルを編集できます。
$ crontab -e
Crontabファイルの各エントリは、スペースで区切られた6つのフィールドで構成されます。最初の5つがcron式を構成し、6番目が実行するコマンドです。例えば、nodeを使用して「index.js」ファイルを実行するとします。通常、コマンドラインで次のコマンドを実行します。
$ node index.js
ただし、このcronエントリには、cron式、nodeへの絶対パス(通常は/usr/local/bin/node)、index.jsファイルへの絶対パスという3項目を含める必要があります。このcronエントリは次のようになります。
0 0 9 * * * [path/to/node] [path/to/index.js]
自分のJavaScriptコードをcrontabファイルにエントリとして追加してみてください。現在スケジュールされているジョブを確認するには、次のコマンドを随時実行します。
$ crontab -l
こうして簡単にnode.jsコードをスケジュールし、すべてのローカルリソースに引き続きアクセスできますが、いくつかの制約が存在します。まず、スケジュールしたコードを実行するには、コンピューターが常にオンラインでなければなりません。マシンを常時稼働しておかなくてもいいように、インターネット上でコードを実行する方法を考えてみます。

Windows

Windows環境では2つの方法があります。まず、Linux用Windowsサブシステムをインストールしてコマンドを実行する方法です。
$bash
Linux環境を実行し、上記のようにcrontabスケジューラを利用できます。もう1つが、powershellやcmdからスケジュールされたWindowsのタスクを使用する方法です。スケジュールされたタスクを使用するには、nodeを起動するバッチファイル(.bat)を作成する必要があります。とてもシンプルなファイルは次のようになります。
WindowsスケジューラはCron式を使用しませんが、所定の間隔で実行されるようジョブをスケジュール設定できます。スケジュールされたタスクを作成し、Node.jsコードを起動するバッチファイルを実行するには、次のコマンドを実行します。
schtasks /create /tn myTask /tr [path/to/.bat/file] /sc DAILY /st 09:00
それぞれパートごとに見てみましょう。次のコマンドにより新しいタスクを作成します。
  • /tn - タスク名。タスク名myTask(注: 一意のタスク名を使用)
  • /tr - タスク実行。スクリプトファイルの絶対パス
  • /sc - スケジュールタイプ。分、時間、週ごと、その他の設定が可能
  • /st - 開始時間。最初のタスクを開始する時間。続くタスクは所定の間隔で実行される
その他にもオプションが多数あり、さらに複雑なスケジュールを設定できます。Microsoftドキュメントの総合ガイドにschtasksの使用法が記載されています。
クラウドサーバー
コードをインターネットで実行するには、何らかのインフラストラクチャサービスが必要になります。AWS EC2、Google Compute Engine、DigitalOcean Droplets、Azure Virtual Machinesなど、多くの一般的サービスが利用できます。サービスの違いについて詳しくは述べませんが、サービスごとに初期セットアップを完了すれば、ローカルで実行したのと同じようにcrontabツールを使用できるようになります。
クラウドサーバーは24時間365日オンラインで使用できる便利な環境であり、インターネットがすぐに崩壊することもないでしょう。しかし、サーバーのセットアップと維持は時間のかかる作業です。また、「常時稼働」のサーバーであるため技術的には料金を支払い続けていますが、多くのプロバイダーが提供している無償サービスの範囲は超えないはずです。
クラウド関数
サーバーの維持は大きな負担がかかり、思う以上に多くの作業を要します。利用期間中に実行するジョブがなくても、年間のサーバー料金が発生する問題もあります。クラウドサービスには、設定したスケジュールで実行できるクラウド関数を提供するものもあります。
こちらに例を挙げます。
  • スケジュールに基づいて実行される関数を Azure portal で作成する
  • チュートリアル: CloudWatch Events を使用して AWS Lambda 関数をスケジュールする
このリストの中にお使いのクラウドホストがなくても、Cronスケジュールジョブを設定できないわけではありません。詳細については、各クラウドホストのドキュメントを確認してください。クラウドサーバーと同じく、Cron関数は常時利用可能で改善がなされ、使用した分だけの料金で済みます。
クラウドトリガー
この方法は上記のクラウド関数と似ており、JavaScriptコードをクラウド関数内でホストする形をとります。下で紹介するような一部のサービスでは、任意のURLに定期的にHTTPリクエストを送ることができ、特定のベンダーに縛られずにすむため便利です。クラウド関数サービスにはCron機能が搭載されていないことが多いため、このオプションは私のお気に入りです。好きなクラウド関数サービスを使い、コードをホストするだけで済みます。私の個人的なお気に入りのクラウド関数はTwilio Functionsです。この関数の起動をスケジュールし、Node.jsコードを実行できます。
クラウドトリガーのいくつかお気に入りをあげておきます。
  • Google Cloud Scheduler
  • Schedule by Zapier、Webhooks by Zapier
  • Cronhooks.io
クラウドトリガーを使用する場合、HTTPリクエストによりコードを起動できるのであれば、コードの場所は問題になりません。このため、特にベンダーにより関数が異なる場合に便利な方法です。しかし、スケジュール設定されたジョブを管理する場所が増えることを意味し、管理対象も増えます。
まとめ
Node.jsのコードが定期的に実行されるようスケジュールを設定するには、さまざまな方法があります。Cronジョブの設定方法には、それぞれ長短があり、開発者のニーズに応じて好みも異なります。個人的には、Twilio FunctionsとGoogle Cloud Schedulerの組み合わせがお気に入りです。サーバーレス環境では、サーバーを稼働する必要なくコードをスケジュール設定できます。すばらしいですね!
皆さんによるJavaScriptコードのスケジュール設定例を楽しみにしています。皆さんの取り組みをこちらまでお知らせください。