こちらのサイトではDRUPAL10に関連する記事を掲載しています。
この記事は以下の「Guide to Ultimate Cron」を翻訳しています。
はじめに
Drupal には独自の組み込み cron が付属しています。 これは、Drupal cron の実行時に実行されるジョブのリストに独自のジョブを追加できることを意味します。
Drupal はこれらすべてのジョブを同時に実行します。 特定の cron ジョブを非常に頻繁に実行したい場合はどうなるでしょうか? すべてを頻繁に実行するには、cron 設定を変更する必要があります。 これは全か無かの問題であり、最終的にはすべての cron ジョブを最も頻繁に実行するジョブと同じ頻度で実行することになります。 これにより、Web サーバーに大きな負荷がかかる可能性があります。
2 つ目の問題は、力仕事が多い仕事をしている場合です。 これらのジョブでは、サイトへのトラフィックが軽く、Web サーバーへの負担が少ない夜間に実行するとよいでしょう。 しかし、Drupal に組み込まれた cron では、その全か無かの性質により、それを行うことはできません。 一度実行するか、まったく実行しないかです。
この問題を解決するには、cron ジョブを分離して、各ジョブまたはジョブのグループを異なる時間に実行できるようにする方法が必要です。 これを実現するには、Elysia Cron と Ultimate Cron という 2 つの主なオプションがあります。 Drupal10で対応しているのはUltimateCronのみです。
モジュールをダウンロードしてインストールする
新しいモジュールをプロジェクトに追加する推奨される方法は、composer を使用することです。 次のコンポーザー コマンドは、Ultimate Cron をダウンロードし、依存関係のリストに追加します。
Ultimate Croneの公式サイトはこちらです
composer require 'drupal/ultimate_cron:^2.0@alpha'
その後、[拡張管理] メニュー項目に移動するか、Drush を使用して、モジュールを手動で有効にすることができます。
新しいジョブを作成する
カスタムモジュールを作成してHOOK_CRONを実装することで新しいジョブを作ることができます 。
次の例では、 hook_cron()
というモジュール内にある Custom_utility関数です。 このジョブが実行されると、Drupal のログにメッセージが記録されます。
function custom_utility_cron() {
\Drupal::logger('custom_utility')->notice('Cron ran');
}
関数内のコードを変更して、必要なものを実行できます。 メッセージをログに記録する呼び出しは、単にこの cron ジョブが実際に実行されていることを示すために行われます。
作成したCRON JOBを登録する
管理メニュー (/admin/config/system/cron/jobs) の [設定] -> [cron] に移動します。 さまざまなコア モジュールからのジョブのリストが表示されるはずです。
「ジョブの検出」ボタンをクリックすると、先に作成したジョブが認識されてリストに表示されるようになります。
これが機能することをテストするには、 「実行」をクリックします。 (admin/reports/dblog)に移動する 次に、最近のログ メッセージと、メッセージが表示されるはずです。
ジョブの頻度を編集するには、「 実行」ボタンの右側にある矢印をクリックし、「編集」をクリックします。 ドロップダウンで頻度を変更できます [スケジューラ] タブで、 [X 分ごとに cron を実行]。
OSのcronに登録する
DrupalのCronは設定したタイミングで自動で実行されるわけではありません。あくまで外部のトリガがによって定期的にCron処理を実行する必要があります。
OSのCron設定に登録するためには、コマンドラインで処理を記述する必要があります。
Drushを使用すると簡単にCronを実行することができます。参考までに以下がDrushでCronを実行するコマンドです。
php ./vendor/drush/drush/drush --uri={ドメイン名} --quiet cron
OSのCron設定は、crontabコマンドに直接記述してもよいですが、手動で実行することや動作確認のことを考慮すると、CRONで実行するためのシェルスクリプトを作成して、crontabにはそのスクリプトを登録するといった方法がよいかもしれません。
以下はそのスクリプトの例です。
2行目がそれですが、絶対パスで指定しています。
echo `date`: `whoami`': cron kicked' >> cron.log ##ログ出力
/opt/kusanagi/php/bin/php /home/kusanagi/prod_chatgpt/chatgpt100/vendor/drush/drush/drush --uri=chatdeoshiete.com --quiet cron
他にもいくつかの方法が公式サイトで説明されています。以下は、公式サイトで説明されているウェブサイトをアスセスしてCronを実行する方法です(いずれでもOK)
45 * * * * /usr/bin/lynx -source http://example.com/cron.php
45 * * * * /usr/bin/wget -O - -q -t 1 http://www.example.com/cron.php
45 * * * * curl -s http://example.com/cron.php
詳しくは、Drupalの公式サイトConfiguring cron jobs using the cron commandおよびAutomated Cronのページをご覧ください。
Configuring cron jobs using the cron command
Automated Cron
設定をエクスポートする
この時点で、Drupal の標準構成エクスポートを使用して構成をエクスポートできます。 ステージング サイトと実稼働サイトを使用する場合は、構成をインポートできます。 を確認してください 構成をエクスポートおよびインポートする方法がわからない場合は、 Drupal.org の構成管理ドキュメント。
モジュールに複数のジョブを追加する
カスタム モジュールが 1 つの cron ジョブのみをサポートする必要がある場合は、これで十分です。cron ジョブがスケジュールされた時間に実行されるときに実行されます。
しかし、この 1 つのカスタム モジュールから複数の cron ジョブを異なる時間に実行したい場合はどうすればよいでしょうか?
これを行うには、複数の cron ジョブをそれぞれ独自のコールバック関数で定義します。
各 Ultimate Cron ジョブの設定は、独自の構成ファイルに保存されます。 Drupal は構成ファイルに YAML を使用するため、これらのファイルを作成する必要があります。 次の手順では、これを行う方法の概要を説明します。
###cron ジョブを追加する手順
- 管理者メニューで、[構成] -> [構成の同期] (/admin/config/development/configuration) に移動します。
- [エクスポート] タブをクリックし、次に [単一項目] サブタブ (/admin/config/development/configuration/single/export) をクリックします。
- 変更します 構成タイプをに Cron ジョブ
- 変更します [構成名] を、カスタム モジュールの名前を使用して [デフォルト cron ハンドラー] に 。 私の場合、これは デフォルトの cron ハンドラー (
custom_utility_cron
). - 構成コードをクリップボードにコピーします
カスタム モジュール内:
- カスタム モジュールのディレクトリのルート直下にconfig/installフォルダを作成します
-
ultimate_cron.job.jobname.yml
をそのフォルダの中に置きます。
このファイルの中身は以下のようになっています。
uuid: fa40bf2b-f544-4e22-b4b9-dda9cc0efbfe
langcode: en
status: true
dependencies:
module:
- custom_utility
title: 'Default cron handler'
id: custom_utility_cron
weight: 0
module: custom_utility
callback: custom_utility_cron
scheduler:
id: simple
configuration:
rules:
- '*/15+@ * * * *'
launcher:
id: serial
configuration:
timeouts:
lock_timeout: 3600
launcher:
thread: 0
logger:
id: database
configuration:
method: '3'
expire: 1209600
retain: 1000
このファイルはそのままでは使用できず、以下のように修正する必要があります。
- uuid 行 (最初の行) を削除します。
- ID を一意の ID に変更します (例: ID:custom_utility_cron_job1)。
- cron 管理ページでこのジョブを区別できるように、タイトルを意味のあるものに変更します。
このファイルは、Drupal が実行する新しいジョブを作成します。
分析してみましょう:
- callback:custom_utilty_cron – これは、このジョブの実行時に実行されるコールバック関数です。
- module: – これはカスタム モジュールです。 これはコールバック関数を追加する必要があるモジュールでもあります
- sスケジューラ: – このジョブが実行されるスケジュールです。この場合は 15 分ごとです。
次に行うことは、モジュール内の .module ファイルにコールバックを追加することです。
以下に例を示します。
/**
* The callback for the cron job.
*/
function custom_utility_callback() {
\Drupal::logger('custom_utility')->notice('Cron ran');
}
このコールバック関数は、このジョブが実行されるたびに実行されます。
次に、上記の構成ファイルに戻り、この関数を指すようにコールバック関数を変更します。 私の例では、これは次の行を変更することを意味します。
callback: custom_utility_cronからcallback: custom_utility_callback に変更します
追加で必要な cron ジョブに対して、上記の手順を繰り返すことで一つのモジュール内に必要なだけCRONジョブを登録することができます。
新しい構成をインポートする
これを機能させるには、上で設定した構成をインポートするか、モジュールの再インストールを行う必要があります。 構成のインポートを行う場合は、次のコマンドで実行できます (custom_utility を対象のモジュールの名前に変更します)。
drush config-import --source=modules/custom/custom_utility/config/install --partial -y
モジュールの再インストールを行う場合は、アンインストール時に構成を削除する必要がありますが未検証です。実際にモジュールを開発する場合はDRUSHコマンドを使わなくて良いようにインストール時にCRON JOBの設定が自動的にできるのが望ましいと思います。
まとめ
多くの場合、異なる時間にジョブを実行するために必要な制御を提供するには、cron ジョブを分離することが必要です。 Ultimate Cron は、まさにそれを可能にする素晴らしいモジュールです。
さらに高度な技術として、Cron ジョブにパラメータ渡しで情報を与えてキューをとして登録しておき、Cron実行時に溜まっていたキューを実行するということも可能です。この方法は、@niibori(Kazuki)さんの「Drupal8のカスタムモジュールをcronに対応させるメモ」でわかりやすく説明されています。(次の参考の章にURLを記載しています)
参考
Drupal8のカスタムモジュールをcronに対応させるメモ
Best practices for using Drupal’s cron system: hook_cron()
https://www.thirdandgrove.com/insights/best-practices-for-using-drupals-cron-system-hook_cron/
この記事またはDrupalに関するご質問がございましたら、お気軽にお問い合わせください。