workerman 5.2.3 必须用 systemd 实现可靠开机自启,禁用 -d、设 type=simple、user 非 root、声明依赖并配置 restart=always,服务文件放 /etc/systemd/system/ 后执行 daemon-reload 再 enable/start。

Workerman 5.2.3 必须通过 systemd 注册为系统服务才能实现可靠开机自启。它不支持 nohup、@reboot 或 /etc/rc.local 等传统方式,因为这些方法无法管理进程生命周期,崩溃后不会自动拉起,也无法声明依赖(比如等 Redis 或 MySQL 就绪后再启动)。
下面是你需要完成的全部步骤,每一步都对应一个常见失败点:
一、确认 Workerman 启动方式符合 systemd 要求
systemd 要求主进程**前台运行**,不能自行 fork 后退出。 Workerman 5.2.3 默认 `start -d` 是后台守护模式,必须禁用: - 启动命令中**不能带 `-d`** - 改用 `--daemon=0`(推荐)或 `start -d=false`例如,正确命令是:
/usr/bin/php /var/www/myapp/start.php start --daemon=0
而不是:
/usr/bin/php /var/www/myapp/start.php start -d ❌
二、创建标准 systemd 服务文件
在 `/etc/systemd/system/` 下新建文件,如 `workerman.service`:[Unit] Description=Workerman Application After=network.target redis-server.service mysql.service Wants=redis-server.service mysql.service [Service] Type=simple User=www-data Group=www-data WorkingDirectory=/var/www/myapp ExecStart=/usr/bin/php /var/www/myapp/start.php start --daemon=0 Restart=always RestartSec=3 StandardOutput=journal StandardError=journal SyslogIdentifier=workerman [Install] WantedBy=multi-user.target
关键点说明:
-
Type=simple:不可写成forking,否则 systemd 会误判启动失败 -
User必须是非 root 用户(如www-data),否则 bind 端口会报Permission denied -
WorkingDirectory设为项目根目录,避免日志路径、配置加载出错 -
After和Wants声明依赖服务(如 Redis、MySQL),确保它们先就绪 -
Restart=always让崩溃后自动重启(但语法错误导致立即退出不算“崩溃”,需靠日志定位)
三、授权并重载配置
执行以下命令(顺序不能错):sudo chmod 644 /etc/systemd/system/workerman.service sudo systemctl daemon-reload sudo systemctl enable workerman.service sudo systemctl start workerman.service
注意:
- 文件权限必须是
644,不是755 -
daemon-reload必须在enable或start之前执行,否则报Unit not found -
enable会创建软链接,让服务在开机时自动激活
四、验证与排错
启动失败时,别反复 `stop/start`,直接看真实日志:- 实时跟踪日志:
sudo journalctl -u workerman -f
- 查最后一次完整启动过程(含 PHP 错误):
sudo journalctl -u workerman --since "1 hour ago"
- 检查服务当前状态:
sudo systemctl status workerman
常见报错及对应解法:
-
inactive (dead):多半是用了-d或Type=forking -
Failed with result 'exit-code':检查start.php是否有语法错误或 require 失败 -
Permission denied:确认User非 root,且该用户对端口、日志目录有读写权限 -
No such file or directory:ExecStart中的 PHP 路径或脚本路径不是绝对路径(用which php确认)
不复杂但容易忽略。











