MQTT 订阅后台运行,关闭终端窗口不中断
方法一:.screen(可随时重新连接查看进程)
适合需要随时查看 / 操作MQTT 订阅进程的场景(比如调试阶段)。
# 1. 安装screen(CentOS/Ubuntu) yum install screen -y # CentOS/RHEL apt install screen -y # Ubuntu/Debian # 2. 创建名为mqtt_sub的screen会话 screen -S mqtt_sub # 3. 在会话内执行订阅命令 php think mqtt:subscribe # 4. 分离会话(保留进程后台运行) # 按快捷键:Ctrl + A → 再按 D # 5. 重新连接会话(查看/操作进程) screen -r mqtt_sub # 6. 终止进程(如需停止) # 重新连接会话后按 Ctrl + C 停止命令,再输入 exit 关闭screen会话
方法二:systemd 服务(生产环境推荐,支持开机自启)(未测试)
适合生产环境,可实现开机自启、进程异常重启、统一日志管理,是最稳定的方案。
步骤 1:创建 systemd 服务文件
# 编辑服务文件(命名为mqtt-subscribe.service)
vim /etc/systemd/system/mqtt-subscribe.service
步骤 2:写入以下配置(需修改路径适配你的项目)
[Unit] Description=ThinkPHP MQTT Subscribe Service After=network.target [Service] # 运行用户(推荐用非root用户,比如www) User=www Group=www # 项目根目录(改为你的ThinkPHP项目路径) WorkingDirectory=/var/www/your-thinkphp-project # 执行命令(改为你的php路径和项目路径) ExecStart=/usr/bin/php think mqtt:subscribe # 进程异常退出时自动重启 Restart=always # 重启间隔(防止无限重启) RestartSec=5 # 日志输出 StandardOutput=append:/var/log/mqtt_subscribe.log StandardError=append:/var/log/mqtt_subscribe.log [Install] # 开机自启的运行级别 WantedBy=multi-user.target
步骤 3:启动并设置开机自启
# 重新加载systemd配置 systemctl daemon-reload # 启动服务 systemctl start mqtt-subscribe # 设置开机自启 systemctl enable mqtt-subscribe # 常用操作 systemctl status mqtt-subscribe # 查看服务状态 systemctl stop mqtt-subscribe # 停止服务 systemctl restart mqtt-subscribe # 重启服务 journalctl -u mqtt-subscribe -f # 实时查看服务日志
总结
- 需要随时操作进程:用
screen(可重连、可交互); - 生产环境长期运行:用
systemd服务(支持开机自启、异常重启,最稳定); - 无论哪种方法,都建议配置日志输出,方便排查订阅异常问题。
附一 怎么查看所有screen会话
查看所有 screen 会话的核心命令
最常用且直接的命令是:
screen -ls
命令输出示例及解读
执行后会看到类似这样的输出,能清晰看到所有会话的状态和名称:
There are screens on: 12345.mqtt_sub (Detached) # 会话ID.会话名,状态为「已分离」(后台运行) 67890.test (Attached) # 状态为「已连接」(有终端正在使用) 2 Sockets in /run/screen/S-root.
补充实用操作(结合你的 MQTT 场景)
# 1. 重连指定名称的会话(最常用) screen -r mqtt_sub # 2. 如果会话名重复,用会话ID重连 screen -r 12345 # 3. 清理「失效/僵死」的screen会话(比如进程已终止但会话残留) screen -wipe # 4. 强制终止某个会话(无需先连接) screen -S 12345 -X quit
强制终止(无需连接,适合无法连接 / 僵死的会话)
如果会话无法连接(比如显示「Dead?」状态),或不想先连接,可直接强制终止:
# 格式:screen -S 会话ID/名称 -X quit screen -S 12345 -X quit # 用会话ID删除 # 或 screen -S mqtt_sub -X quit # 用会话名删除
特殊情况:清理「僵死 / 失效」会话
# 清理僵死会话 screen -wipe # 再次查看,确认无效会话已被移除 screen -ls
极端情况:通过 kill 命令杀进程(兜底方案)
如果以上方法都无效,可直接找到 screen 进程并终止:
# 1. 查找screen相关进程 ps -ef | grep screen # 2. 找到对应会话的进程ID(PID),执行强制终止 kill -9 进程PID
总结
- 常规删除:先
screen -r 会话ID/名称连接,再输入exit或按Ctrl+D; - 快速删除:直接执行
screen -S 会话ID/名称 -X quit(无需连接); - 僵死会话:先
screen -wipe清理,再用上述方法删除。
附二现在php think mqtt:subscribe会订阅2次,怎么查询是否有2个进程?
核心查询命令(精准定位 MQTT 订阅进程)
直接执行以下命令,能过滤出所有和
php think mqtt:subscribe 相关的进程,且排除 grep 自身的干扰:ps -ef | grep "php think mqtt:subscribe" | grep -v grep
输出示例及解读
如果存在 2 个重复进程,输出会类似这样(重点看每行开头的进程 ID(PID) 和命令行):
root 12345 1 0 10:00 ? 00:00:01 php think mqtt:subscribe root 67890 1 0 10:01 ? 00:00:00 php think mqtt:subscribe
- 每行代表一个独立进程;
12345/67890是进程 ID(PID),是区分不同进程的核心标识;- 若输出有 2 行及以上,说明确实存在多个 MQTT 订阅进程;
- 若只有 1 行,说明进程数量正常。
补充:更直观的计数方式(直接看进程数量)
如果只想快速知道有多少个该进程,执行以下命令会直接输出数字(比如输出
2就代表有 2 个进程):ps -ef | grep "php think mqtt:subscribe" | grep -v grep | wc -l
额外场景:排查 screen 中的重复会话 / 进程
如果你的 MQTT 订阅是通过
screen运行的,还需要排查是否创建了多个 screen 会话导致重复进程:# 1. 查看所有screen会话 screen -ls # 2. 查看某个screen会话内的进程(比如会话名是mqtt_sub) screen -r mqtt_sub -X ps aux
处理重复进程(可选)
如果确认有多个重复进程,可通过 PID 终止多余的进程:
# 终止指定PID的进程(比如终止67890这个进程) kill -9 67890 # 若用systemd服务运行,先停止服务再重启(避免重复启动) systemctl stop mqtt-subscribe # 确认进程全部终止后再重启 ps -ef | grep "php think mqtt:subscribe" | grep -v grep systemctl start mqtt-subscribe
总结
- 精准查询进程:执行
ps -ef | grep "php think mqtt:subscribe" | grep -v grep,看输出行数判断是否有多个进程; - 快速计数:用
ps -ef | grep "php think mqtt:subscribe" | grep -v grep | wc -l直接获取进程数量; - 若有重复进程,通过
kill -9 进程PID终止多余进程,或重启 systemd 服务清理重复实例。

浙公网安备 33010602011771号