后台脚本
后台脚本适用于持续运行类型的脚本。后台脚本是脚本猫特有的脚本,后台脚本运行在沙盒中,无法操作 DOM 对象。可使用与油猴一致的 GM API 进行开发,对于兼容性会在文档中标出。
后台脚本 (@background)
后台脚本由 @background 属性声明,后台脚本将允许在开启脚本或者浏览器启动后,让脚本在后台持续运行。
定时脚本(@crontab)
定时脚本属于后台脚本的一种,适用于按时间周期重复执行的任务。
定时脚本通过 @crontab 属性声明,支持分钟级与秒级调度,并提供脚本猫扩展语法 once,用于避免在同一时间周期内重复执行。
⚠️ 注意事项:
- 一个脚本中 只有第一个
@crontab会生效 - 建议脚本的单次执行时间 + 重试时间不要大于 cron 间隔,否则可能发生执行重叠
Cron 表达式说明
脚本猫的 cron 基于 node-cron 实现,在标准 cron 语法上做了少量扩展。
表达式格式
标准 5 位格式(推荐)
分 时 日 月 周
扩展 6 位格式(不推荐)
秒 分 时 日 月 周
⚠️ 不推荐使用 6 位格式 浏览器环境无法保证秒级精准执行,并且会增加性能开销,后台页可能被延迟调度。
各字段可用语法
| 语法 | 含义 | 示例 |
|---|---|---|
* | 任意值 | *(每分钟 / 每小时) |
| 数字 | 指定值 | 5(第 5 分) |
a,b,c | 多个离散值 | 1,15,30 |
a-b | 连续区间 | 10-23 |
*/n | 每 n 执行一次 | */5 |
a-b/n | 区间步长 | 10-50/10 |
周(day of week)规则
1–6:周一 ~ 周六0或7:周日
once 扩展语法说明
once 的含义
在 cron 表达式中使用 once,表示:
在当前时间周期内,只允许成功执行一次
即使在同一周期内,后续时间点仍然符合 cron 规则,也不会再次执行。
once 所在位置 = 限制的时间周期
once 写在哪一位,就表示“在该时间粒度内只执行一次”。
once 位置 | 行为含义 |
|---|---|
| 分位 | 每分钟只执行一次 |
| 时位 | 每小时只执行一次 |
| 日位 | 每天只执行一次 |
| 月位 | 每月只执行一次 |
| 周位 | 每周只执行一次 |
示例:
* once * * * // 每小时只执行一次
* * once * * // 每天只执行一次
once 与范围 / 列表 / 步长的组合行为
once 可以与任何 cron 语法组合使用,但规则只有一条:
在同一周期内,只要成功执行过一次,其余命中的时间点都会被忽略
示例一:范围
* 10 once * *
含义:
- 每天 10:00–10:59 都是候选时间
- 当天第一次命中后
- 10:05–10:59 将不再执行
示例二:列表
* 1,3,5 once * *
含义:
- 每天 1 点、3 点、5 点是候选时间
- 若 1 点已执行
- 3 点、5 点将被忽略
示例三:步长
* */4 once * *
含义:
- 每天 0、4、8、12、16、20 点是候选时间
- 当天第一次执行后
- 其余时间点将不再执行
@crontab 示例
常 见
//@crontab * * * * * // 每分钟执行一次
//@crontab * * * * * * // 每秒执行一次(不推荐)
//@crontab 0 */6 * * * // 每 6 小时整点执行
//@crontab 15 */6 * * * // 每 6 小时的第 15 分执行
//@crontab * once * * * // 每小时最多执行一次
//@crontab * * once * * // 每天最多执行一次
//@crontab * 10 once * * // 每天 10 点时段内只执行一次 (假设当10:04时运行了一次,10:05-10:59的后续的时间将不会再运行)
//@crontab * */4 once * * // 每天每 4 小时检查一次(最多一次) (假设当4点时运行了一次,8,12,16,20,24点等后续的时间将不会再运行)
进阶
//@crontab * 1,3,5 once * * // 每天1点3点5点中运行一次(假设当1点时运行了一次,3,5点将不会再运行)
//@crontab * 10-23 once * * // 每天10点-23:59中运行一次(假设当10:04时运行了一次,10:05-23:59的后续时间将不会再运行)
//@crontab * once 13 * * // 每个月的13号的每小时运行一次
使用建议
适合使用 once 的场景
-
每天 / 每小时 只需要执行一次 的任务
-
状态检查、同步、上报类脚本
-
避免以下问题:
- 浏览器长时间未打开
- 后台页调度延迟
- 浏览器重启导致的重复执行
不建议使用 once 的场景
- 必须精确在某一时刻执行的任务
- 执行时间可能明显超过 cron 间隔的脚本
- 对执行次数有强一致性要求的任务
Cron 表达式测试
测试 cron 表达式时,请将 once 临时替换为 *。
注意测试工具有可能不支持 扩展 6 位格式。
推荐工具:
在脚本列表页面中,将鼠标放在 运行状态栏 上,可查看脚本的下一次执行时间。
日志
在脚本列表页面,鼠标放置在 运行状态栏 上,会提示脚本的运行状态,
点击后可弹出通过 GM_log 打印的日志内容。

脚本调试
后台脚本可以直接在脚本编辑页面进行调试,但存在以下问题:
- value 无法正常同步
- registerMenu 菜单无法正常触发

如果需要调试真实运行环境,请前往扩展设置中开启 开发人员模式,
然后打开扩展的 background.html 页面进行调试。
运行时产生的错误也可以在运行日志中查看。

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 每天运行一次的定时脚本
// @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 操作将不会生效。
错误重试
脚本猫后台脚本支持错误重试。
当脚本执行失败时,可以 reject 一个 CATRetryError 来触发重试。
- 最小重试时间: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错误", 10));
});