メインコンテンツまでスキップ

バックグラウンドスクリプト

バックグラウンドスクリプトは、常に実行を継続する必要があるスクリプトに適しています。バックグラウンドスクリプトは ScriptCat 固有のスクリプトタイプです。サンドボックスで実行され、DOM にアクセスできません。Tampermonkey と同じ GM API を使用して開発でき、互換性に関する注記はドキュメントに記載されています。

バックグラウンドスクリプト(@background

バックグラウンドスクリプトは @background 属性で宣言します。スクリプトが有効化された後やブラウザが起動した後も、スクリプトをバックグラウンドで継続的に実行できます。

スケジュールスクリプト(@crontab

スケジュールスクリプトは、一定のサイクルで繰り返し実行する必要があるタスク に適したバックグラウンドスクリプトの一種です。

スケジュールスクリプトは @crontab 属性で宣言します。分レベルおよび秒レベルのスケジュールをサポートし、同じタイムサイクル内で複数回実行されるのを防ぐ ScriptCat の拡張構文 once / once(...) を提供します。

⚠️ 注意事項:

  • 1つのスクリプトで 最初の @crontab のみが有効 です
  • スクリプトの 単一実行時間 + リトライ時間 が cron 間隔を超えないことをお勧めします。超えると実行が重複する可能性があります

Cron 式の注意事項

ScriptCat の cron 実装は node-cron をベースにしており、標準の cron 構文に小さな拡張を加えています。

式の形式

標準5フィールド形式(推奨)

分 時 日 月 曜日

拡張6フィールド形式(非推奨)

秒 分 時 日 月 曜日

⚠️ 6フィールド形式は非推奨です ブラウザ環境では秒レベルの精度を保証できず、パフォーマンスのオーバーヘッドが増加します。バックグラウンドページのスケジュールが遅延する可能性があります。

各フィールドで使用可能な構文

構文意味
*任意の値*(毎分/毎時)
number特定の値5(5分)
a,b,c複数の離散値1,15,30
a-b連続範囲10-23
*/nn単位ごと*/5
a-b/nステップ付き範囲10-50/10

曜日のルール

  • 1–6:月曜日から土曜日
  • 0 または 7:日曜日

once 拡張構文

once の意味

cron 式で once を使用すると:

現在のタイムサイクル内で1回の成功した実行のみを許可

同じサイクル内の後続の時刻ポイントが cron ルールにマッチしても、スクリプトは再実行されません。

onceonce(...) の比較

構文このフィールドの基礎cron値説明
once*(任意の値)サイクル内で最初のマッチ時に実行。特定の時刻なし
once(expr)exprサイクル内で expr にマッチする時刻のみ実行。1回のみ

once(expr) を使うと、候補時刻を正確に指定しながら「サイクルごとに1回のみ実行」を適用できます。括弧内ではすべての標準 cron 構文(数値、範囲、ステップ、リスト)がサポートされています。

比較例:

* once * * * // 毎時の任意の分。最初のマッチで実行、その時間の残りは再実行しない
* once(9-17) * * * // 毎日9:00〜17:59の間、1時間に1回実行
0,30 once * * * // 0分または30分のうち最初にマッチしたものが毎時実行。その時間の残りは再実行しない

once の位置 = 制限するタイムサイクル

once / once(...) をどこに配置しても、「その時間粒度内で1回のみ実行」を意味します。

once の位置動作
分フィールド1分に1回のみ実行
時フィールド1時間に1回のみ実行
日フィールド1日に1回のみ実行
月フィールド1ヶ月に1回のみ実行
曜日フィールド1週間に1回のみ実行

例:

* once * * * // 1時間に1回のみ実行
* * once * * // 1日に1回のみ実行
* 9-18 once * * // 毎日9:00〜18:59の間、1回のみ実行

once と範囲/リスト/ステップの組み合わせ

once / once(...) は任意の cron 構文と組み合わせできますが、ルールは1つだけです:

同じサイクル内で一度実行が成功すると、その後のすべてのマッチする時刻ポイントは無視されます

例1:範囲

* 10 once * *

意味:

  • 毎日10:00〜10:59が候補時刻
  • 1回目のマッチ後
  • 10:05〜10:59は再実行されない

例2:リスト

* 1,3,5 once * *

意味:

  • 毎日1:00、3:00、5:00が候補時刻
  • 1:00で実行済みの場合
  • 3:00と5:00はスキップされる

例3:ステップ

* */4 once * *

意味:

  • 毎日0:00、4:00、8:00、12:00、16:00、20:00が候補時刻
  • 1回目の実行後
  • その後の時刻ポイントは実行されない

例4:once(...) で候補時刻を指定

* once(9-17) * * *

意味:

  • 毎日9:00〜17:00が候補時刻
  • 時ごとにサイクルがリセット。1時間以内で最初のマッチが後続の実行を停止
  • 効果:毎日9:00〜17:00の間、1時間に1回、計9回実行
* 9-18 once * *

意味:

  • 毎日9:00〜18:59が候補時刻
  • 日フィールドの once がサイクルを1日に1回にロック
  • 1回目のマッチ後、18:59まで再実行されない

@crontab の例

一般的

//@crontab * * * * * // 1分ごとに実行
//@crontab * * * * * * // 1秒ごとに実行(非推奨)
//@crontab 0 */6 * * * // 6時間ごとに0分に実行
//@crontab 15 */6 * * * // 6時間ごとに15分に実行
//@crontab * once * * * // 1時間に最大1回実行
//@crontab * * once * * // 1日に最大1回実行
//@crontab * 10 once * * // 毎日10時の時間帯に1回のみ実行(例:10:04に実行済みなら10:05-10:59は再実行しない)
//@crontab * */4 once * * // 毎日4時間ごとに最大1回チェック(例:4:00に実行済みなら8、12、16、20、24などは再実行しない)

応用

//@crontab * 1,3,5 once * * // 毎日1:00、3:00、5:00のうち1回のみ実行
//@crontab * 10-23 once * * // 毎日10:00〜23:59の間、1回のみ実行
//@crontab * once 13 * * // 毎月13日に1時間に1回実行
//@crontab * once(9-17) * * * // 毎日9:00〜17:00の間、1時間に1回実行
//@crontab 0,30 once * * * // 0分または30分のうち最初にマッチしたものが毎時実行。その時間の残りは再実行しない
//@crontab * 9-18 once * * // 毎日9:00〜18:00の間、1回のみ実行

使用上の推奨

once に適したタスク

  • 1日/1時間に1回のみ実行 が必要なタスク
  • ステータスチェック、同期、レポートスクリプト
  • 以下の問題の回避:
    • ブラウザが長時間開かれていない
    • バックグラウンドページのスケジュール遅延
    • ブラウザの再起動による重複実行

once が推奨されないタスク

  • 正確な時刻に実行する必要があるタスク
  • 実行時間が cron 間隔を大幅に超える可能性のあるスクリプト
  • 実行回数に厳格な整合性要件があるタスク

Cron 式のテスト

cron 式をテストする際は、once / once(...) を基礎値に一時的に置き換えてください

  • once*
  • once(expr)expr

テストツールは6フィールド形式をサポートしていない場合があることをご了承ください。

推奨ツール:

スクリプトリストページでは、実行状態列 にカーソルを合わせるとスクリプトの 次回実行予定時刻 を確認できます。

ログ

スクリプトリストページでは、run status column にカーソルを合わせるとスクリプトの実行状態を示すツールチップが表示されます。 クリックすると GM_log で出力されたログコンテンツがポップアップ表示されます。

スクリプトのデバッグ

バックグラウンドスクリプトはスクリプトエディタページから直接デバッグできますが、以下の制限があります:

  • value が正しく同期されない
  • registerMenu メニューが正しくトリガーされない

実際のランタイム環境をデバッグするには、拡張機能の設定で 開発者モード を有効にし、拡張機能の background.html ページを開いてデバッグしてください。

ランタイムで発生したエラーは実行ログで確認することもできます。

image-20210903144155450

Promise

以下のパターンを強くお勧めします。スクリプト管理ツールがスクリプトの実行を監視できるようになります。 スクリプトが非同期操作を実行する場合、Promise を返す必要があります

// ==UserScript==
// @name バックグラウンドスクリプト
// @namespace wyz
// @version 1.0.0
// @author wyz
// @background
// ==/UserScript==
return new Promise((resolve, reject) => {
if (Math.round((Math.random() * 10) % 2)) {
resolve("ok"); // 成功
} else {
reject("error"); // 失敗、エラー理由付き
}
});
// ==UserScript==
// @name 1日に1回実行されるスケジュールスクリプト
// @namespace wyz
// @version 1.0.0
// @author wyz
// @crontab * * once * *
// ==/UserScript==
return new Promise((resolve, reject) => {
if (Math.round((Math.random() * 10) % 2)) {
resolve("ok"); // 成功
} else {
reject("error"); // 失敗、エラー理由付き
}
});
// ==UserScript==
// @name API呼び出し
// @namespace wyz
// @version 1.0.0
// @author wyz
// @crontab * * once * *
// ==/UserScript==
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: "https://bbs.tampermonkey.net.cn/",
onload() {
resolve("ok"); // 成功
},
onerror() {
reject("error"); // 失敗、エラー理由付き
},
});
});

スクリプトのロジックが実際に完了した後にのみ resolve / reject を呼び出してください。 呼び出された後、管理ツールはスクリプトの実行が完了したと見なし、それ以降のGM操作は効果がありません。

エラーリトライ

ScriptCat のバックグラウンドスクリプトはエラーリトライをサポートしています。 スクリプトが失敗した場合、CATRetryErrorreject してリトライをトリガーできます。

  • 最小リトライ間隔:5秒
  • スクリプトの実行時間と競合しないようにしてください。競合すると重複実行が発生する可能性があります
// ==UserScript==
// @name リトライ例
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.0
// @description try to take over the world!
// @author You
// @crontab * * once * *
// @grant GM_notification
// ==/UserScript==

return new Promise((resolve, reject) => {
GM_notification({
title: "retry",
text: "10秒後にリトライします",
});
reject(new CATRetryError("xxx error", 10));
});