Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp8_EleVue/.vitepress/dist/assets/zh_modules_job.md.D49eZjCP.lean.js
T
2026-10-25 18:52:36 +08:00

360 lines
132 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B-QBKwc1.js";const g=JSON.parse('{"title":"定时任务","description":"定时任务系统由三部分组成:JobLogic(调度逻辑)+ BaseTask(任务处理器)+ JobRunCommand(命令行入口)。","frontmatter":{},"headers":[],"relativePath":"zh/modules/job.md","filePath":"zh/modules/job.md"}'),h={name:"zh/modules/job.md"};function l(p,s,k,e,d,r){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="_6-11-定时任务" tabindex="-1">6.11 定时任务 <a class="header-anchor" href="#_6-11-定时任务" aria-label="Permalink to &quot;6.11 定时任务&quot;">​</a></h1><div class="tip custom-block"><p class="custom-block-title">概述</p><p>定时任务系统由三部分组成:JobLogic(调度逻辑)+ BaseTask(任务处理器)+ JobRunCommand(命令行入口)。支持三种触发方式:Linux Crontab、Windows 计划任务、Daemon 守护进程。</p></div><h2 id="系统架构" tabindex="-1">系统架构 <a class="header-anchor" href="#系统架构" aria-label="Permalink to &quot;系统架构&quot;">​</a></h2><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 触发层(三选一) │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │</span></span>
<span class="line"><span>│ │ Linux Crontab│ │Windows 计划 │ │ Daemon 守护 │ │</span></span>
<span class="line"><span>│ │ │ │任务 │ │ 进程 │ │</span></span>
<span class="line"><span>│ │ * * * * * │ │ schtasks │ │ php think │ │</span></span>
<span class="line"><span>│ │ php think │ │ │ │ job:daemon │ │</span></span>
<span class="line"><span>│ │ job:run │ │ │ │ │ │</span></span>
<span class="line"><span>│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │</span></span>
<span class="line"><span>│ │ │ │ │</span></span>
<span class="line"><span>│ └─────────────────┼─────────────────┘ │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ ┌─────────────────────────┐ │</span></span>
<span class="line"><span>│ │ JobRunCommand │ │</span></span>
<span class="line"><span>│ │ php think job:run │ │</span></span>
<span class="line"><span>│ │ 或 php think job:daemon│ │</span></span>
<span class="line"><span>│ └────────────┬────────────┘ │</span></span>
<span class="line"><span>└───────────────────────────┼─────────────────────────────────────┘</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 调度层(JobLogic) │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ runPending() shouldRun() │</span></span>
<span class="line"><span>│ ├─ 查询 status=1 的任务 ├─ 解析 cron 表达式 │</span></span>
<span class="line"><span>│ ├─ 逐个判断是否到执行时间 ├─ 分 时 日 月 周 逐段匹配 │</span></span>
<span class="line"><span>│ └─ 到期则执行 └─ 全部匹配返回 true │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ executeJob($job) │</span></span>
<span class="line"><span>│ ├─ 检查执行策略(立即/排队/放弃) │</span></span>
<span class="line"><span>│ ├─ 调用 doExecute() 实际执行 │</span></span>
<span class="line"><span>│ ├─ 记录 JobLog 执行日志 │</span></span>
<span class="line"><span>│ └─ 返回执行结果 │</span></span>
<span class="line"><span>└───────────────────────────┼─────────────────────────────────────┘</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 执行层 │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ doExecute($job) │</span></span>
<span class="line"><span>│ ├─ 判断 URL 类型 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ├─ http:// / https:// → executeHttp() │</span></span>
<span class="line"><span>│ │ └─ curl 发起 HTTP GET/POST 请求 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ └─ 其它 → executeInternal() │</span></span>
<span class="line"><span>│ └─ 映射到 app\\task\\{Name}Task::run() │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ 示例: │</span></span>
<span class="line"><span>│ url = &quot;SendSms&quot; → app\\task\\SendSmsTask::run() │</span></span>
<span class="line"><span>│ url = &quot;Order/Close&quot; → app\\task\\Order\\CloseTask::run() │</span></span>
<span class="line"><span>│ url = &quot;https://...&quot; → HTTP GET/POST │</span></span>
<span class="line"><span>└─────────────────────────────────────────────────────────────────┘</span></span></code></pre></div><h2 id="状态说明" tabindex="-1">状态说明 <a class="header-anchor" href="#状态说明" aria-label="Permalink to &quot;状态说明&quot;">​</a></h2><table tabindex="0"><thead><tr><th>状态值</th><th>说明</th><th>可执行</th><th>可暂停</th><th>可启动</th></tr></thead><tbody><tr><td>0</td><td>未发布</td><td>✗</td><td>✗</td><td>✓</td></tr><tr><td>1</td><td>运行中</td><td>✓</td><td>✓</td><td>✗</td></tr><tr><td>2</td><td>暂停</td><td>✗</td><td>✗</td><td>✓</td></tr><tr><td>3</td><td>已删除</td><td>✗</td><td>✗</td><td>✗</td></tr></tbody></table><h2 id="执行策略" tabindex="-1">执行策略 <a class="header-anchor" href="#执行策略" aria-label="Permalink to &quot;执行策略&quot;">​</a></h2><table tabindex="0"><thead><tr><th>策略值</th><th>说明</th><th>行为</th></tr></thead><tbody><tr><td>1</td><td>立即执行</td><td>丢弃之前的执行,立即运行</td></tr><tr><td>2</td><td>执行一次</td><td>等待上一次完成后执行</td></tr><tr><td>3</td><td>放弃执行</td><td>如果上一次还在运行则跳过</td></tr></tbody></table><div class="tip custom-block"><p class="custom-block-title">枚举文本自动翻译</p><p>JobLogic 配置了 <code>serializeMaps</code>,API 响应中会自动包含翻译后的文本字段:</p><table tabindex="0"><thead><tr><th>原始字段</th><th>文本字段</th><th>字典编码</th><th>说明</th></tr></thead><tbody><tr><td><code>status</code></td><td><code>statusText</code></td><td><code>job_status</code></td><td>任务状态(未发布/运行中/暂停/删除)</td></tr><tr><td><code>execute_policy</code></td><td><code>executePolicyText</code></td><td><code>job_execute_policy</code></td><td>执行策略(立即执行/执行一次/放弃执行)</td></tr></tbody></table><p>字典数据在代码生成器自动创建,也可在「系统管理 → 字典管理」中手动维护。</p></div><h2 id="Cron-表达式语法" tabindex="-1">Cron 表达式语法 <a class="header-anchor" href="#Cron-表达式语法" aria-label="Permalink to &quot;Cron 表达式语法&quot;">​</a></h2><p>标准 5 段格式:<code>分 时 日 月 周</code></p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌────────── 分钟(0-59)</span></span>
<span class="line"><span>│ ┌──────── 小时(0-23)</span></span>
<span class="line"><span>│ │ ┌────── 日(1-31)</span></span>
<span class="line"><span>│ │ │ ┌──── 月(1-12)</span></span>
<span class="line"><span>│ │ │ │ ┌── 周(0-6,0=周日)</span></span>
<span class="line"><span>│ │ │ │ │</span></span>
<span class="line"><span>* * * * *</span></span></code></pre></div><table tabindex="0"><thead><tr><th>表达式</th><th>说明</th></tr></thead><tbody><tr><td><code>* * * * *</code></td><td>每分钟</td></tr><tr><td><code>0 * * * *</code></td><td>每小时整点</td></tr><tr><td><code>0 0 * * *</code></td><td>每天 0 点</td></tr><tr><td><code>0 2 * * *</code></td><td>每天凌晨 2 点</td></tr><tr><td><code>0 0 * * 1</code></td><td>每周一 0 点</td></tr><tr><td><code>0 0 1 * *</code></td><td>每月 1 号 0 点</td></tr><tr><td><code>*/5 * * * *</code></td><td>每 5 分钟</td></tr><tr><td><code>0 */2 * * *</code></td><td>每 2 小时</td></tr><tr><td><code>0 9-18 * * 1-5</code></td><td>工作日 9-18 点每小时</td></tr><tr><td><code>0 2 1,15 * *</code></td><td>每月 1 号和 15 号凌晨 2 点</td></tr></tbody></table><hr><h2 id="方式一-Linux-Crontab-推荐-" tabindex="-1">方式一:Linux Crontab(推荐) <a class="header-anchor" href="#方式一-Linux-Crontab-推荐-" aria-label="Permalink to &quot;方式一:Linux Crontab(推荐)&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">适用场景</p><p>Linux / macOS 服务器,最常用的定时任务触发方式。系统级 cron 每分钟触发一次 PHP 命令。</p></div><h3 id="配置步骤" tabindex="-1">配置步骤 <a class="header-anchor" href="#配置步骤" aria-label="Permalink to &quot;配置步骤&quot;">​</a></h3><h4 id="_1-编辑-crontab" tabindex="-1">1. 编辑 crontab <a class="header-anchor" href="#_1-编辑-crontab" aria-label="Permalink to &quot;1. 编辑 crontab&quot;">​</a></h4><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -e</span></span></code></pre></div><h4 id="_2-添加定时任务" tabindex="-1">2. 添加定时任务 <a class="header-anchor" href="#_2-添加定时任务" aria-label="Permalink to &quot;2. 添加定时任务&quot;">​</a></h4><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 每分钟执行一次(推荐)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">*</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> cd /www/api </span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&amp;&amp;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:run</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;&gt;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /dev/null</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> 2&gt;&amp;1</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 每分钟执行一次,日志写入文件(调试用)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">*</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> cd /www/api </span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&amp;&amp;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:run</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;&gt;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /var/log/job.log</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> 2&gt;&amp;1</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 每分钟执行一次,带环境变量</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">*</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> cd /www/api </span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&amp;&amp;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> /usr/bin/php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:run</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;&gt;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /dev/null</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> 2&gt;&amp;1</span></span></code></pre></div><div class="warning custom-block"><p class="custom-block-title">路径注意</p><ul><li><code>cd /www/api</code> 必须切换到项目根目录,否则 ThinkPHP 无法找到配置文件</li><li><code>php</code> 建议使用绝对路径(如 <code>/usr/bin/php</code>),避免 cron 环境变量不同导致找不到 PHP</li><li><code>&gt;&gt; /dev/null 2&gt;&amp;1</code> 表示丢弃输出,调试时可改为写入日志文件</li></ul></div><h4 id="_3-保存并验证" tabindex="-1">3. 保存并验证 <a class="header-anchor" href="#_3-保存并验证" aria-label="Permalink to &quot;3. 保存并验证&quot;">​</a></h4><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 保存后 cron 自动生效</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看已配置的 cron</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -l</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看 cron 日志(确认是否正常触发)</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">tail</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -f</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /var/log/syslog</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> |</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> grep</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> CRON</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 手动执行一次验证</span></span>
<span class="line"><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">cd</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /www/api</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> &amp;&amp;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:run</span></span></code></pre></div><h4 id="_4-权限设置" tabindex="-1">4. 权限设置 <a class="header-anchor" href="#_4-权限设置" aria-label="Permalink to &quot;4. 权限设置&quot;">​</a></h4><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 确保 PHP 有权限执行</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">chmod</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> +x</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /usr/bin/php</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 确保项目目录权限</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">chmod</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -R</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 755</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /www/api/runtime/</span></span></code></pre></div><h3 id="Crontab-常用命令" tabindex="-1">Crontab 常用命令 <a class="header-anchor" href="#Crontab-常用命令" aria-label="Permalink to &quot;Crontab 常用命令&quot;">​</a></h3><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -e</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> # 编辑当前用户的 cron</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -l</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> # 列出当前用户的 cron</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -r</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> # 删除当前用户的所有 cron(慎用)</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -u</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> username</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -l</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> # 查看指定用户的 cron</span></span></code></pre></div><h3 id="系统-cron-目录" tabindex="-1">系统 cron 目录 <a class="header-anchor" href="#系统-cron-目录" aria-label="Permalink to &quot;系统 cron 目录&quot;">​</a></h3><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>/etc/crontab # 系统级 cron 配置</span></span>
<span class="line"><span>/etc/cron.d/ # 额外的 cron 配置文件目录</span></span>
<span class="line"><span>/etc/cron.daily/ # 每天执行的脚本</span></span>
<span class="line"><span>/etc/cron.hourly/ # 每小时执行的脚本</span></span>
<span class="line"><span>/etc/cron.weekly/ # 每周执行的脚本</span></span>
<span class="line"><span>/etc/cron.monthly/ # 每月执行的脚本</span></span></code></pre></div><hr><h2 id="方式二-Windows-计划任务" tabindex="-1">方式二:Windows 计划任务 <a class="header-anchor" href="#方式二-Windows-计划任务" aria-label="Permalink to &quot;方式二:Windows 计划任务&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">适用场景</p><p>Windows Server 或本地开发环境,通过任务计划程序定时触发。</p></div><h3 id="方式-A-图形界面配置" tabindex="-1">方式 A:图形界面配置 <a class="header-anchor" href="#方式-A-图形界面配置" aria-label="Permalink to &quot;方式 A:图形界面配置&quot;">​</a></h3><h4 id="_1-打开任务计划程序" tabindex="-1">1. 打开任务计划程序 <a class="header-anchor" href="#_1-打开任务计划程序" aria-label="Permalink to &quot;1. 打开任务计划程序&quot;">​</a></h4><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>方法1:Win + R → 输入 taskschd.msc → 回车</span></span>
<span class="line"><span>方法2:控制面板 → 管理工具 → 任务计划程序</span></span>
<span class="line"><span>方法3:开始菜单搜索&quot;任务计划程序&quot;</span></span></code></pre></div><h4 id="_2-创建基本任务" tabindex="-1">2. 创建基本任务 <a class="header-anchor" href="#_2-创建基本任务" aria-label="Permalink to &quot;2. 创建基本任务&quot;">​</a></h4><ol><li>右侧点击&quot;创建基本任务&quot;</li><li>名称:<code>RXThinkCMF 定时任务</code></li><li>描述:<code>每分钟执行一次定时任务扫描</code></li><li>触发器:选择&quot;每天&quot;</li><li>开始时间:设置当前时间</li><li>重复任务间隔:<code>1 分钟</code></li><li>持续时间:<code>无限期</code></li><li>操作:选择&quot;启动程序&quot;</li><li>程序或脚本:</li></ol><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>C:\\xampp\\php\\php.exe</span></span></code></pre></div><ol start="10"><li>添加参数:</li></ol><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>think job:run</span></span></code></pre></div><ol start="11"><li>起始于:</li></ol><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>D:\\xampp8.2\\htdocs\\RXThinkCMF_ThinkPhp8_EleVue</span></span></code></pre></div><ol start="12"><li>勾选&quot;不管用户是否登录都要运行&quot;</li><li>点击完成</li></ol><h4 id="_3-验证" tabindex="-1">3. 验证 <a class="header-anchor" href="#_3-验证" aria-label="Permalink to &quot;3. 验证&quot;">​</a></h4><div class="language-powershell vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">powershell</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 手动运行测试</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">cd D:\\xampp8.</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">2</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">\\htdocs\\RXThinkCMF_ThinkPhp8_EleVue</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">C:\\xampp\\php\\</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">php.exe</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> think job:run</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 在任务计划程序中右键任务 → 运行</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看&quot;上次运行结果&quot;是否为 0x0</span></span></code></pre></div><h3 id="方式-B-命令行配置-schtasks-" tabindex="-1">方式 B:命令行配置(schtasks) <a class="header-anchor" href="#方式-B-命令行配置-schtasks-" aria-label="Permalink to &quot;方式 B:命令行配置(schtasks)&quot;">​</a></h3><div class="language-powershell vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">powershell</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 创建每分钟执行的任务</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">create </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tr </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">C:\\xampp\\php\\php.exe think job:run</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">sc minute </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">mo </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">st </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">00</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">:</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">00</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">f</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 参数说明:</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /tn 任务名称</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /tr 要执行的命令</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /sc 频率:minute(分钟)、hourly(小时)、daily(天)</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /mo 间隔:1 表示每 1 分钟</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /st 开始时间</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># /f 强制覆盖同名任务</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 创建任务(指定工作目录)</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">create </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tr </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">cmd /c cd /d D:\\xampp8.2\\htdocs\\RXThinkCMF_ThinkPhp8_EleVue &amp;&amp; C:\\xampp\\php\\php.exe think job:run</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">sc minute </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">mo </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">f</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查询任务</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">query </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 手动运行</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">run </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 删除任务</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">delete </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">f</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看所有任务</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">query </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">fo table</span></span></code></pre></div><h3 id="Windows-注意事项" tabindex="-1">Windows 注意事项 <a class="header-anchor" href="#Windows-注意事项" aria-label="Permalink to &quot;Windows 注意事项&quot;">​</a></h3><div class="warning custom-block"><p class="custom-block-title">常见问题</p><ol><li><strong>路径空格</strong>:如果路径含空格,需要用引号包裹</li><li><strong>PHP 路径</strong>:使用 <code>php.exe</code> 的完整路径</li><li><strong>工作目录</strong>:必须设置为项目根目录</li><li><strong>权限</strong>:确保任务以有权限的用户身份运行</li><li><strong>日志</strong>:可在参数中添加 <code>&gt;&gt; log.txt 2&gt;&amp;1</code> 重定向输出</li></ol></div><div class="language-powershell vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">powershell</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 带日志输出的完整命令</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">schtasks </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">create </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tn </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">tr </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">cmd /c cd /d D:\\xampp8.2\\htdocs\\RXThinkCMF_ThinkPhp8_EleVue &amp;&amp; C:\\xampp\\php\\php.exe think job:run &gt;&gt; runtime\\job.log 2&gt;&amp;1</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">sc minute </span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">/</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">mo </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> /</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">f</span></span></code></pre></div><hr><h2 id="方式三-Daemon-守护进程" tabindex="-1">方式三:Daemon 守护进程 <a class="header-anchor" href="#方式三-Daemon-守护进程" aria-label="Permalink to &quot;方式三:Daemon 守护进程&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">适用场景</p><p>需要更精确的执行时机(秒级),或不想依赖系统 cron 的场景。进程常驻内存,自行调度。</p></div><h3 id="原理" tabindex="-1">原理 <a class="header-anchor" href="#原理" aria-label="Permalink to &quot;原理&quot;">​</a></h3><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>Daemon 进程启动</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>┌─────────────────────┐</span></span>
<span class="line"><span>│ while (true) │ 无限循环</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ├─ runPending() │ 扫描并执行到期任务</span></span>
<span class="line"><span>│ ├─ sleep(60) │ 休眠 60 秒</span></span>
<span class="line"><span>│ └─ 继续循环 │</span></span>
<span class="line"><span>└─────────────────────┘</span></span></code></pre></div><h3 id="实现方式" tabindex="-1">实现方式 <a class="header-anchor" href="#实现方式" aria-label="Permalink to &quot;实现方式&quot;">​</a></h3><h4 id="方式-A-使用-Supervisor-管理-推荐生产环境-" tabindex="-1">方式 A:使用 Supervisor 管理(推荐生产环境) <a class="header-anchor" href="#方式-A-使用-Supervisor-管理-推荐生产环境-" aria-label="Permalink to &quot;方式 A:使用 Supervisor 管理(推荐生产环境)&quot;">​</a></h4><p>创建命令文件:</p><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// app/command/JobDaemonCommand.php</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">&lt;?</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">php</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">declare</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">strict_types</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">namespace</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;">command</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">use</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> think</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">console</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Command</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">use</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> think</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">console</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Input</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">use</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> think</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">console</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Output</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">use</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">logic</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">JobLogic</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">/**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 定时任务守护进程命令</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 常驻内存运行,每分钟扫描并执行到期任务。</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 建议通过 Supervisor 管理,确保进程异常退出后自动重启。</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 用法:php think job:daemon</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">class</span><span style="--shiki-dark:#97E1F1;--shiki-light:#2E8F82;"> JobDaemonCommand</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> extends</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#59873A;--shiki-light-font-style:inherit;"> Command</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> configure</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> void</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#BF9EEE;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;"> $</span><span style="--shiki-dark:#BF9EEE;--shiki-dark-font-style:italic;--shiki-light:#A65E2B;--shiki-light-font-style:inherit;">this</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">setName</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">job:daemon</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">setDescription</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">定时任务守护进程(常驻内存)</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> execute</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Input</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">input</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> Output</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">output</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> void</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">output</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">writeln</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">[</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">] Daemon 启动...</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">logic</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> new</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> JobLogic</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> while</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;">true</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> try</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">count</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">logic</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">runPending</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> ($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">count</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">output</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">writeln</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">[</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">] 执行了 </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">count</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> 个任务</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> catch</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Exception</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">e</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">output</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">writeln</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">[</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">] 异常: </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">e</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">getMessage</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">());</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 休眠 60 秒</span></span>
<span class="line"><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> sleep</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">60</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><p>Supervisor 配置:</p><div class="language-ini vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ini</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">; /etc/supervisor/conf.d/rxthinkcmf-job.conf</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#59873A;">program:rxthinkcmf-job</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">command</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">php /www/api/think job:daemon</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">directory</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">/www/api</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">autostart</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">true</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">autorestart</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">true</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">user</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">www-data</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">numprocs</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">1</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">redirect_stderr</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">true</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">stdout_logfile</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">/var/log/rxthinkcmf-job.log</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">stdout_logfile_maxbytes</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">10MB</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">stdout_logfile_backups</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">5</span></span></code></pre></div><p>启动:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 重新加载配置</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> supervisorctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> reread</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> supervisorctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> update</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 启动</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> supervisorctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> start</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看状态</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> supervisorctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> status</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 重启</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> supervisorctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> restart</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看日志</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">tail</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -f</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /var/log/rxthinkcmf-job.log</span></span></code></pre></div><h4 id="方式-B-Windows-CMD-运行" tabindex="-1">方式 B:Windows CMD 运行 <a class="header-anchor" href="#方式-B-Windows-CMD-运行" aria-label="Permalink to &quot;方式 B:Windows CMD 运行&quot;">​</a></h4><p>在项目根目录打开 CMD,执行以下命令:</p><div class="language-cmd vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cmd</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">:: 启动 Daemon(前台运行,关闭窗口则停止)</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">php think job:daemon</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">:: 停止 Daemon(另开一个 CMD 窗口执行)</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">php think job:</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">daemon</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> --</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">stop</span></span></code></pre></div><p><strong>启动成功输出:</strong></p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>[2026-09-23 09:06:07] Daemon 已启动 (PID: 22720)</span></span>
<span class="line"><span>[2026-09-23 09:06:07] 每分钟检查一次到期任务,按 Ctrl+C 优雅退出</span></span></code></pre></div><p><strong>运行过程中的日志输出:</strong></p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>[2026-09-23 11:25:00] [执行] 定时任务演示 (cron: */5 * * * *)</span></span>
<span class="line"><span>[2026-09-23 11:25:00] [执行] 定时任务案例 (cron: */5 * * * *)</span></span>
<span class="line"><span>[2026-09-23 11:25:00] 本轮执行完成,共执行 2 个任务</span></span>
<span class="line"><span>[2026-09-23 11:30:00] [执行] 定时任务演示 (cron: */5 * * * *)</span></span>
<span class="line"><span>[2026-09-23 11:30:00] [跳过] 定时任务案例 - 当前分钟已执行过</span></span>
<span class="line"><span>[2026-09-23 11:30:00] 本轮执行完成,共执行 1 个任务</span></span></code></pre></div><p>日志类型说明:</p><table tabindex="0"><thead><tr><th>标记</th><th>含义</th></tr></thead><tbody><tr><td><code>[执行]</code></td><td>任务已触发执行,括号内显示 cron 表达式</td></tr><tr><td><code>[跳过]</code></td><td>同一分钟内该任务已执行过,自动跳过(防重复)</td></tr><tr><td><code>[失败]</code></td><td>任务执行异常,后跟错误信息</td></tr><tr><td><code>本轮执行完成</code></td><td>当前分钟的所有任务扫描完毕,显示执行数量</td></tr></tbody></table><div class="tip custom-block"><p class="custom-block-title">提示</p><ul><li>没有到期任务时,Daemon 不输出任何日行(静默等待),属于正常行为</li><li><code>[跳过]</code> 是防重复机制,同一任务在同一分钟内只会执行一次</li><li>出现 <code>[失败]</code> 时检查对应的任务处理器代码,单个任务失败不影响其他任务</li></ul></div><p><strong>前端联动:</strong> Daemon 启动后,后台管理系统的「定时任务」模块会自动检测到守护进程状态,页面顶部显示:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌──────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ [新增] [删除] [🟢 守护进程运行中 (PID: 22720)] │</span></span>
<span class="line"><span>└──────────────────────────────────────────────────────┘</span></span></code></pre></div><ul><li>绿色「守护进程运行中」按钮 — 表示 Daemon 正常工作,鼠标悬停可查看 PID</li><li>灰色「守护进程未运行」— 表示 Daemon 未启动或已停止</li></ul><div class="tip custom-block"><p class="custom-block-title">状态检测原理</p><p>前端通过 <code>GET /api/job/daemonStatus</code> 接口轮询状态,后端读取 <code>runtime/job_daemon.lock</code> 锁文件中的 PID 并检查进程是否存活。因此即使 Daemon 非正常退出(如强制杀进程),只要锁文件残留,前端仍可能显示「运行中」,此时需手动删除 <code>runtime/job_daemon.lock</code> 或执行 <code>php think job:daemon --stop</code> 清理。</p></div><div class="warning custom-block"><p class="custom-block-title">Windows 注意事项</p><ol><li><strong>无信号扩展</strong>:Windows 不支持 <code>pcntl_signal</code>,<code>Ctrl+C</code> 会强制终止进程而非优雅退出</li><li><strong>停止方式</strong>:推荐使用 <code>php think job:daemon --stop</code>,或关闭 CMD 窗口</li><li><strong>防重复启动</strong>:命令内部通过文件锁(<code>runtime/job_daemon.lock</code>)防止重复启动,启动前会自动检测并提示 <code>Daemon 已在运行中 (PID: xxx)</code></li><li><strong>后台运行</strong>:如需后台运行,可使用 <code>start /B php think job:daemon</code>,停止时用 <code>php think job:daemon --stop</code></li><li><strong>窗口关闭即停止</strong>:前台运行时关闭 CMD 窗口会终止进程,生产环境建议配合 Windows 服务或计划任务守护</li></ol></div><h4 id="方式-C-nohup-后台运行-简单场景-" tabindex="-1">方式 C:nohup 后台运行(简单场景) <a class="header-anchor" href="#方式-C-nohup-后台运行-简单场景-" aria-label="Permalink to &quot;方式 C:nohup 后台运行(简单场景)&quot;">​</a></h4><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 后台启动</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">nohup</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /www/api/think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:daemon</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;&gt;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /var/log/job.log</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> 2&gt;&amp;1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> &amp;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看进程</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">ps</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> aux</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> |</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> grep</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:daemon</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 停止</span></span>
<span class="line"><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">kill</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $(</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">pgrep</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -f</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">job:daemon</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span></span></code></pre></div><h4 id="方式-D-systemd-服务-推荐-" tabindex="-1">方式 D:systemd 服务(推荐) <a class="header-anchor" href="#方式-D-systemd-服务-推荐-" aria-label="Permalink to &quot;方式 D:systemd 服务(推荐)&quot;">​</a></h4><div class="language-ini vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ini</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">; /etc/systemd/system/rxthinkcmf-job.service</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#59873A;">Unit</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">Description</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">RXThinkCMF Job Daemon</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">After</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">network.target mysql.service</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#59873A;">Service</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">Type</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">simple</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">User</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">www-data</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">WorkingDirectory</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">/www/api</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">ExecStart</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">/usr/bin/php /www/api/think job:daemon</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">Restart</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">always</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">RestartSec</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">10</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#59873A;">Install</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">WantedBy</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">multi-user.target</span></span></code></pre></div><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 启用并启动</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> systemctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> enable</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> systemctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> start</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看状态</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> systemctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> status</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 查看日志</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> journalctl</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -u</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -f</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 重启</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">sudo</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> systemctl</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> restart</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> rxthinkcmf-job</span></span></code></pre></div><hr><h2 id="三种方式对比" tabindex="-1">三种方式对比 <a class="header-anchor" href="#三种方式对比" aria-label="Permalink to &quot;三种方式对比&quot;">​</a></h2><table tabindex="0"><thead><tr><th>特性</th><th>Crontab</th><th>Windows 计划任务</th><th>Daemon 守护进程</th></tr></thead><tbody><tr><td>适用系统</td><td>Linux / macOS</td><td>Windows</td><td>全平台</td></tr><tr><td>最小间隔</td><td>1 分钟</td><td>1 分钟</td><td>1 秒</td></tr><tr><td>资源占用</td><td>低(按需启动)</td><td>低(按需启动)</td><td>常驻内存</td></tr><tr><td>可靠性</td><td>高</td><td>高</td><td>高(配合 Supervisor)</td></tr><tr><td>配置复杂度</td><td>低</td><td>中</td><td>低</td></tr><tr><td>日志追踪</td><td>需重定向</td><td>任务计划程序</td><td>自带输出</td></tr><tr><td>推荐场景</td><td>生产环境</td><td>Windows 生产</td><td>需要秒级精度 / 开发调试</td></tr></tbody></table><div class="tip custom-block"><p class="custom-block-title">推荐选择</p><ul><li><strong>Linux 生产环境</strong>:Crontab(简单可靠)</li><li><strong>Windows 生产环境</strong>:任务计划程序 或 Daemon 守护进程</li><li><strong>需要秒级精度</strong>:Daemon + Supervisor</li><li><strong>Docker 环境</strong>:Daemon(容器内运行)</li><li><strong>本地开发调试</strong>:Daemon 前台运行(直接观察日志输出)</li></ul></div><hr><h2 id="新建定时任务步骤" tabindex="-1">新建定时任务步骤 <a class="header-anchor" href="#新建定时任务步骤" aria-label="Permalink to &quot;新建定时任务步骤&quot;">​</a></h2><h3 id="_1-创建任务处理器" tabindex="-1">1. 创建任务处理器 <a class="header-anchor" href="#_1-创建任务处理器" aria-label="Permalink to &quot;1. 创建任务处理器&quot;">​</a></h3><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">&lt;?</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">php</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// app/task/CleanLogTask.php</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">declare</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">strict_types</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">namespace</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;">task</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">/**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 清理过期日志任务</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 数据库 url 字段:CleanLog</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 参数格式:{&quot;days&quot;: 30}</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">class</span><span style="--shiki-dark:#97E1F1;--shiki-light:#2E8F82;"> CleanLogTask</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> extends</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#59873A;--shiki-light-font-style:inherit;"> BaseTask</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 执行任务</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@param</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> $params 任务参数</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@return</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> 执行结果消息</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@throws</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;"> \\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">Exception</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> 执行失败时抛出</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> public</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> run</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">params</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [])</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">days</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">params</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">days</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ??</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 30</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cutoffDate</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> strtotime</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">-</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B56959;">days</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> days</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 清理登录日志</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">loginCount</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;"> \\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">model</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">LoginLog</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">create_time</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&lt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cutoffDate</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">delete</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 清理操作日志</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">operCount</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;"> \\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">model</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">OperationLog</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">create_time</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&lt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cutoffDate</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">delete</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 清理任务日志</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">jobCount</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;"> \\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">app</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">model</span><span style="--shiki-dark:#F286C4;--shiki-dark-font-style:italic;--shiki-light:#999999;--shiki-light-font-style:inherit;">\\</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">JobLog</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">start_time</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&lt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cutoffDate</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">delete</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">已清理 </span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">{</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B56959;">days</span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> 天前的日志:登录日志 </span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">{</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B56959;">loginCount</span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> 条,操作日志 </span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">{</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B56959;">operCount</span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> 条,任务日志 </span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">{</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B56959;">jobCount</span><span style="--shiki-dark:#E7EE98;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> 条</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><h3 id="_2-在数据库-job-表中配置" tabindex="-1">2. 在数据库 job 表中配置 <a class="header-anchor" href="#_2-在数据库-job-表中配置" aria-label="Permalink to &quot;2. 在数据库 job 表中配置&quot;">​</a></h3><div class="language-sql vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">INSERT INTO</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> think_job (</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> job_name, job_alias, job_group, job_trigger,</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> url</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, params, cron_expression,</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> execute_policy, </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">status</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, is_sync,</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> is_delete, create_user, create_time</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">) </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">VALUES</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;"> (</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">清理过期日志</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">CleanLog</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">系统维护</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">cron</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">CleanLog</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">{&quot;days&quot;:30}</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">0 2 * * *</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">,</span></span>
<span class="line"><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 2</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">,</span></span>
<span class="line"><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">admin</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">, </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">NOW</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">);</span></span></code></pre></div><h3 id="_3-配置触发方式-三选一-" tabindex="-1">3. 配置触发方式(三选一) <a class="header-anchor" href="#_3-配置触发方式-三选一-" aria-label="Permalink to &quot;3. 配置触发方式(三选一)&quot;">​</a></h3><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 方式一:Linux Crontab</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">crontab</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> -e</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 添加:* * * * * cd /www/api &amp;&amp; php think job:run &gt;&gt; /dev/null 2&gt;&amp;1</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 方式二:Windows 计划任务</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">schtasks</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /create</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /tn</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">RXThinkCMF_Job</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /tr</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">cmd /c cd /d D:\\xampp8.2\\htdocs\\RXThinkCMF_ThinkPhp8_EleVue &amp;&amp; C:\\xampp\\php\\php.exe think job:run</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /sc</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> minute</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /mo</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 1</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> /f</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 方式三:Daemon 守护进程</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">php</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> think</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;"> job:daemon</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"># 停止:php think job:daemon --stop</span></span></code></pre></div><hr><h2 id="API-接口" tabindex="-1">API 接口 <a class="header-anchor" href="#API-接口" aria-label="Permalink to &quot;API 接口&quot;">​</a></h2><table tabindex="0"><thead><tr><th>方法</th><th>路径</th><th>权限码</th><th>说明</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/job/page</code></td><td>sys:job:page</td><td>分页列表</td></tr><tr><td>GET</td><td><code>/api/job/list</code></td><td>sys:job:list</td><td>全量列表</td></tr><tr><td>GET</td><td><code>/api/job/detail/:id</code></td><td>sys:job:detail</td><td>详情</td></tr><tr><td>GET</td><td><code>/api/job/runOnce/:id</code></td><td>sys:job:execute</td><td>手动执行一次</td></tr><tr><td>GET</td><td><code>/api/job/pause/:id</code></td><td>sys:job:pause</td><td>暂停任务</td></tr><tr><td>GET</td><td><code>/api/job/resume/:id</code></td><td>sys:job:resume</td><td>恢复任务</td></tr><tr><td>GET</td><td><code>/api/job/daemonStatus</code></td><td>-</td><td>守护进程状态</td></tr><tr><td>POST</td><td><code>/api/job/add</code></td><td>sys:job:add</td><td>新增任务</td></tr><tr><td>POST</td><td><code>/api/job/status</code></td><td>sys:job:update</td><td>设置状态</td></tr><tr><td>PUT</td><td><code>/api/job/update</code></td><td>sys:job:update</td><td>修改任务</td></tr><tr><td>DELETE</td><td><code>/api/job/delete/:id</code></td><td>sys:job:delete</td><td>删除任务</td></tr><tr><td>DELETE</td><td><code>/api/job/batchDelete</code></td><td>sys:job:batchDelete</td><td>批量删除</td></tr></tbody></table><h3 id="任务日志" tabindex="-1">任务日志 <a class="header-anchor" href="#任务日志" aria-label="Permalink to &quot;任务日志&quot;">​</a></h3><table tabindex="0"><thead><tr><th>方法</th><th>路径</th><th>权限码</th><th>说明</th></tr></thead><tbody><tr><td>GET</td><td><code>/api/job/log/page</code></td><td>sys:job:log:page</td><td>日志分页</td></tr><tr><td>GET</td><td><code>/api/job/log/detail/:id</code></td><td>sys:job:log:detail</td><td>日志详情</td></tr><tr><td>DELETE</td><td><code>/api/job/log/delete/:id</code></td><td>sys:job:log:delete</td><td>删除日志</td></tr><tr><td>DELETE</td><td><code>/api/job/log/batchDelete</code></td><td>sys:job:log:batchDelete</td><td>批量删除</td></tr></tbody></table><hr><h2 id="核心代码解析" tabindex="-1">核心代码解析 <a class="header-anchor" href="#核心代码解析" aria-label="Permalink to &quot;核心代码解析&quot;">​</a></h2><h3 id="Cron-表达式匹配-JobLogic-matchCronField-" tabindex="-1">Cron 表达式匹配(JobLogic::matchCronField) <a class="header-anchor" href="#Cron-表达式匹配-JobLogic-matchCronField-" aria-label="Permalink to &quot;Cron 表达式匹配(JobLogic::matchCronField)&quot;">​</a></h3><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// app/logic/JobLogic.php</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">/**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 匹配 cron 字段</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 支持以下语法:</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * - *:匹配所有</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * - */</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">n:每隔</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> n</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> 个单位</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> n</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">m:范围匹配</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> n</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">...</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;">:逗号分隔的多值</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> *</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#A65E2B;"> n:单个值精确匹配</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> matchCronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">string</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> bool</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> ($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ===</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">*</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> true</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 处理 */n(每隔 n 分钟/小时等)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">preg_match</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">&#39;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">^</span><span style="--shiki-dark:#F286C4;--shiki-light:#BDA437;">\\*\\/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#BDA437;">\\d</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">$</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">/&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">))</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> %</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#AB5959;--shiki-light-font-style:inherit;">int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ===</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 处理 n-m(范围)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">preg_match</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">&#39;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">^</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#BDA437;">\\d</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)-(</span><span style="--shiki-dark:#F286C4;--shiki-light:#BDA437;">\\d</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">$</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">/&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">))</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#AB5959;--shiki-light-font-style:inherit;">int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &amp;&amp;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &lt;=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#AB5959;--shiki-light-font-style:inherit;">int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">m</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">2</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 处理逗号分隔的多个值</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">strpos</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> !==</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> false</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">values</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> array_map</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">intval</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> explode</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">));</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> in_array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">values</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 单个值</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#AB5959;--shiki-light-font-style:inherit;">int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">cronField</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ===</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">current</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><h3 id="防重复执行-JobLogic-hasRunThisMinute-" tabindex="-1">防重复执行(JobLogic::hasRunThisMinute) <a class="header-anchor" href="#防重复执行-JobLogic-hasRunThisMinute-" aria-label="Permalink to &quot;防重复执行(JobLogic::hasRunThisMinute)&quot;">​</a></h3><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">/**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 检查任务在当前分钟是否已执行过</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * Daemon 模式下,防止同一分钟内重复执行。</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">public</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> hasRunThisMinute</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">int</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">jobId</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> bool</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">minuteStart</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">:00</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">minuteEnd</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> .</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">:59</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> JobLog</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">job_id</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">jobId</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">start_time</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&gt;=</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">minuteStart</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">where</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">start_time</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&lt;=</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">minuteEnd</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> -&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">count</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &gt;</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><hr><h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">​</a></h2><h3 id="Q-任务不执行-" tabindex="-1">Q: 任务不执行? <a class="header-anchor" href="#Q-任务不执行-" aria-label="Permalink to &quot;Q: 任务不执行?&quot;">​</a></h3><p>A: 检查以下几点:</p><ol><li>任务状态是否为 <code>1</code>(运行中)</li><li>Cron 表达式格式是否正确(5 段)</li><li>Crontab 是否已配置且 cron 服务已启动</li><li>PHP 路径是否正确(建议使用绝对路径)</li><li>手动执行 <code>php think job:run</code> 是否正常</li></ol><h3 id="Q-任务重复执行-" tabindex="-1">Q: 任务重复执行? <a class="header-anchor" href="#Q-任务重复执行-" aria-label="Permalink to &quot;Q: 任务重复执行?&quot;">​</a></h3><p>A: Daemon 模式下检查 <code>hasRunThisMinute</code> 是否生效。Crontab 模式下确保只有一个 cron 在触发。</p><h3 id="Q-任务执行超时-" tabindex="-1">Q: 任务执行超时? <a class="header-anchor" href="#Q-任务执行超时-" aria-label="Permalink to &quot;Q: 任务执行超时?&quot;">​</a></h3><p>A: 检查 PHP 的 <code>max_execution_time</code> 配置,长时间任务建议使用 Daemon 模式或设置 <code>set_time_limit(0)</code>。</p><h3 id="Q-如何查看任务执行日志-" tabindex="-1">Q: 如何查看任务执行日志? <a class="header-anchor" href="#Q-如何查看任务执行日志-" aria-label="Permalink to &quot;Q: 如何查看任务执行日志?&quot;">​</a></h3><p>A: 两种方式:</p><ol><li><strong>控制台实时日志</strong>:Daemon 前台运行时,<code>[执行]</code>、<code>[跳过]</code>、<code>[失败]</code> 等日志直接输出到终端</li><li><strong>数据库持久化日志</strong>:通过 API <code>/api/job/log/page</code> 查询,或直接查 <code>think_job_log</code> 表</li></ol><h3 id="Q-Daemon-控制台没有新日志输出-是卡住了吗-" tabindex="-1">Q: Daemon 控制台没有新日志输出,是卡住了吗? <a class="header-anchor" href="#Q-Daemon-控制台没有新日志输出-是卡住了吗-" aria-label="Permalink to &quot;Q: Daemon 控制台没有新日志输出,是卡住了吗?&quot;">​</a></h3><p>A: 不是。Daemon 每分钟检查一次,没有到期任务时静默等待,不输出任何日志。这是正常行为,说明当前没有任务需要执行。</p><h3 id="Q-Windows-下-Daemon-如何启动和停止-" tabindex="-1">Q: Windows 下 Daemon 如何启动和停止? <a class="header-anchor" href="#Q-Windows-下-Daemon-如何启动和停止-" aria-label="Permalink to &quot;Q: Windows 下 Daemon 如何启动和停止?&quot;">​</a></h3><p>A: 在项目根目录打开 CMD:</p><div class="language-cmd vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cmd</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">:: 启动</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">php think job:daemon</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">:: 停止(另开一个 CMD 窗口)</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">php think job:</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">daemon</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> --</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">stop</span></span></code></pre></div><p>启动成功输出:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>[2026-09-23 09:06:07] Daemon 已启动 (PID: 22720)</span></span>
<span class="line"><span>[2026-09-23 09:06:07] 每分钟检查一次到期任务,按 Ctrl+C 优雅退出</span></span></code></pre></div><p>启动后,后台管理系统「定时任务」模块顶部会显示绿色「守护进程运行中」按钮(带 PID 提示),表示 Daemon 正常工作。</p><p>如提示 <code>Daemon 已在运行中 (PID: xxx)</code>,先执行 <code>php think job:daemon --stop</code> 停止旧进程,或手动删除 <code>runtime/job_daemon.lock</code> 文件。</p>`,128)])])}const o=i(h,[["render",l]]);export{g as __pageData,o as default};