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  # 实时查看服务日志

总结

  1. 需要随时操作进程:用screen(可重连、可交互);
  2. 生产环境长期运行:用systemd服务(支持开机自启、异常重启,最稳定);
  3. 无论哪种方法,都建议配置日志输出,方便排查订阅异常问题。
 
 附一 怎么查看所有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

总结

 
  1. 常规删除:先 screen -r 会话ID/名称 连接,再输入 exit 或按 Ctrl+D
  2. 快速删除:直接执行 screen -S 会话ID/名称 -X quit(无需连接);
  3. 僵死会话:先 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

总结

 
  1. 精准查询进程:执行 ps -ef | grep "php think mqtt:subscribe" | grep -v grep,看输出行数判断是否有多个进程;
  2. 快速计数:用 ps -ef | grep "php think mqtt:subscribe" | grep -v grep | wc -l 直接获取进程数量;
  3. 若有重复进程,通过 kill -9 进程PID 终止多余进程,或重启 systemd 服务清理重复实例。
 
posted @ 2026-01-12 09:51  zhang_you_wu  阅读(3)  评论(0)    收藏  举报