symfony 7.0 定时任务必须显式注册命令、配置合法5字段cron表达式并持续运行调度器进程;缺一不可,且错误无提示。需创建命令类、在scheduler.yaml中严格声明任务、用scheduler:debug验证、生产用systemd守护、开发用单次运行,并重定向日志避免静默失败。

在 Symfony 7.0 中创建定时任务,必须显式注册命令、配置合法的 5 字段 cron 表达式,并确保调度器进程持续运行;漏掉任一环节,任务都不会触发,且不会报错提示。
第一步:创建可调度的控制台命令
执行命令生成新命令类:php bin/console make:command app:send-daily-report。
打开生成的 src/Command/SendDailyReportCommand.php,在 configure() 方法中确认命令名严格为 【app:send-daily-report】(不含空格、大小写敏感、连字符不可省略);若此处写成 app:send_daily_report 或 app:send-dailyreport,后续配置将完全失效。
在 execute() 方法中编写实际业务逻辑,例如发送邮件或写入日志。
第二步:在 scheduler.yaml 中声明任务
确保项目已安装 symfony/scheduler 组件:composer require symfony/scheduler。
在 config/packages/scheduler.yaml 中添加如下配置:
tasks: send_daily_report: command: 'app:send-daily-report' schedule: '0 9 * * *'
注意:schedule 必须是标准 Unix 5 字段格式(分 时 日 月 周),不支持 @daily、*/10 * * * * *(6 字段)、或任何中文/别名写法;写错会导致 php bin/console scheduler:debug 显示 never,但无语法错误提示。
第三步:验证与调试任务配置
运行命令查看任务状态:php bin/console scheduler:debug。
如果输出中某任务的“Next run”列为 never,立即检查两处:【command 名称是否与 configure() 中完全一致】、schedule 字段是否含非法字符或多余空格。
开发阶段可手动触发一次:php bin/console scheduler:run --no-debug;该命令会立即执行所有已到时间点的任务,适合快速验证逻辑是否正常。
第四步:让调度器在生产环境持续运行
方法一:systemd 守护进程(推荐用于生产)
创建 systemd service 文件 /etc/systemd/system/symfony-scheduler.service,内容包含:ExecStart=/usr/bin/php /var/www/myapp/bin/console scheduler:run --env=prod
启用并启动:systemctl daemon-reload && systemctl enable --now symfony-scheduler。
方法二:后台常驻进程(仅限开发或测试)
执行:php bin/console scheduler:run --no-debug &;注意该方式无崩溃自动恢复能力,进程退出后任务即停止。
⚠️ 不要在 .env 文件中设置 APP_ENV=dev 的环境下长期运行 scheduler:run;开发环境默认禁用 OPcache 和部分缓存机制,可能导致内存泄漏或执行延迟。
第五步:捕获执行结果,避免静默失败
在 config/packages/scheduler.yaml 中为任务添加日志重定向:
send_daily_report: command: 'app:send-daily-report' schedule: '0 9 * * *' output: '%kernel.logs_dir%/scheduler-daily-report.log' error_output: '%kernel.logs_dir%/scheduler-daily-report-error.log'
这一步至关重要——默认情况下,命令的 stdout 和 stderr 全部被丢弃;即使命令因数据库连接失败、权限不足或未加载环境变量而抛出异常,你也看不到任何线索。











