symfony命令调度需显式注册、合法cron表达式和可控执行环境:命令须在scheduler.yaml中声明且名称严格匹配,schedule用5字段unix格式,输出需重定向日志,推荐生产用systemd守护、开发用单次运行。

Symfony 命令调度不是“写完命令就自动跑”,而是需要显式注册、精确配置、主动管理。核心在于:命令必须被 Scheduler 明确识别,时间表达式必须合法,执行环境必须可控。
显式注册命令,不能靠自动扫描
Symfony Scheduler 不会遍历所有 Command 类。即使你继承了 Command 并正确设置了命令名(如 app:send-daily-report),若未在配置中声明,它就完全不会被加载。
- 在
config/packages/scheduler.yaml中定义任务:tasks: send_daily_report: command: 'app:send-daily-report' schedule: '0 9 * * *' -
command值必须与命令类中configure()方法里设置的名称**完全一致**(大小写、连字符、空格都不能错) - 确保该命令类已作为服务注册——默认启用
autoconfigure时通常满足;若手动关闭过,需显式加标签:tags: ['console.command']
写对 schedule 表达式,避开常见陷阱
Scheduler 使用标准 Unix cron 格式(5 字段),不支持别名(如 @daily)或秒字段(6 字段)。写错会导致任务永远不触发,且无报错提示。
- ✅ 正确示例:
'0 2 * * *'(每天凌晨 2 点)、'*/10 * * * *'(每 10 分钟) - ❌ 错误示例:
'@hourly'(不识别)、'0 */2 * * * *'(多一个字段,解析失败) - 开发时用
php bin/console scheduler:debug查看下次执行时间;如果显示 never,基本就是表达式语法问题
让执行结果可见,别让它静默失败
默认情况下,Scheduler 会丢弃命令的 stdout 和 stderr。命令因权限、环境变量缺失或抛出异常而失败,你也看不到任何线索。
- 在
scheduler.yaml中为任务添加日志重定向:send_daily_report: command: 'app:send-daily-report' schedule: '0 9 * * *' output: '/var/log/symfony/daily-report.log' error_output: '/var/log/symfony/daily-report-error.log'
- 生产环境建议配合
systemd或 supervisord 守护进程运行php bin/console scheduler:run,避免进程意外退出 - 避免在
dev环境常驻运行调度器;开发调试推荐单次执行:php bin/console scheduler:run --no-debug
用 CommandTask 复用命令,注意参数写法
除了 YAML 配置,也可用 PHP 服务方式注册任务,例如通过 CommandTask 包裹已有命令。这种方式更灵活,但参数传递有固定格式。
- 错误写法:
new CommandTask('app:send-email --to=admin@example.com')→ 把整个字符串当命令名,找不到 - 正确写法:
new CommandTask('app:send-email', ['--to' => 'admin@example.com']) - 布尔选项如
--force要写成['--force' => true],不能只写['--force'] - 别在构造函数里用
bind:注入额外依赖传给CommandTask—— 它只接受两个参数,多一个就会导致服务实例化失败并跳过











