You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RPi3(CentOS7) SSH检测LED脚本作为systemd服务异常求助

我来帮你捋捋这个问题——咱们先从进程终止失败的核心原因说起,再一步步搞定systemd服务的异常。

问题分析与解决方案

1. 进程终止失败的核心原因

你提到手动发送-2(SIGINT)信号能关闭LED,但脚本里没法终止Python进程,大概率是信号没有精准发送到目标进程,或者你没正确记录Python脚本的PID。

常见错误点&修复方式:

  • 错误1:未记录Python脚本的PID
    启动Python脚本时必须把它的PID存下来,不然后续没法针对性发送信号。修改启动逻辑:

    # 启动LED脚本并将PID写入临时文件
    python3 your_led_script.py &
    echo $! > /tmp/ssh_led_script.pid
    

    终止时读取PID并发送信号:

    # 读取PID并发送SIGINT信号
    PID=$(cat /tmp/ssh_led_script.pid)
    kill -2 $PID
    # 等待进程优雅退出,清理PID文件
    wait $PID 2>/dev/null
    rm -f /tmp/ssh_led_script.pid
    
  • 错误2:进程匹配/信号选择错误
    如果用pkill python3这种方式杀进程,很可能误杀其他Python程序,一定要精准定位你的LED脚本进程。另外,部分Python脚本会忽略SIGINT,可以先尝试SIGTERM(kill -15),如果还是不行再用SIGKILL(kill -9)——优先用优雅信号,避免强制终止带来的问题。

  • 错误3:权限不匹配
    如果bash脚本通过systemd运行,可能和你手动运行的用户不一致,导致PID文件读写失败,或者没有权限给Python进程发信号。要确保systemd服务的运行用户和Python进程的用户一致,或者赋予足够的权限。

2. SSH连接检测的准确性优化

你当前的ssh_status=disconnected只是初始化值,得确保检测逻辑不会误判。推荐两种可靠的检测方式:

# 方式1:通过who命令检测SSH登录会话(排除自身进程)
ssh_connections=$(who | grep -c "pts/" | grep -v $$)
if [ $ssh_connections -gt 0 ]; then
  ssh_status=connected
else
  ssh_status=disconnected
fi

或者用ss命令检测22端口的活跃连接:

# 方式2:检测22端口的ESTABLISHED状态连接
ssh_connections=$(ss -t state established '( dport = :22 or sport = :22 )' | wc -l)
# 减去ss命令自身的输出行
if [ $((ssh_connections - 1)) -gt 0 ]; then
  ssh_status=connected
else
  ssh_status=disconnected
fi

3. Systemd服务不符合预期的修复

脚本作为systemd服务运行时,常见问题是服务类型设置错误、缺少循环检测逻辑、日志无输出,或者权限配置不当。

正确的systemd服务文件示例(/etc/systemd/system/ssh-led-monitor.service):

[Unit]
Description=SSH Connection LED Monitor
After=network.target

[Service]
Type=simple
User=pi  # 替换成你运行脚本的用户
ExecStart=/path/to/your_monitor_script.sh
Restart=always  # 脚本意外退出时自动重启
RestartSec=5
StandardOutput=journal+console  # 日志输出到journalctl,方便调试

[Install]
WantedBy=multi-user.target

完善脚本的循环检测逻辑

脚本需要持续运行检测SSH状态,不能只执行一次。完整的循环示例:

#!/bin/bash
# 初始化状态
ssh_status=disconnected
led_status=off
PID_FILE="/tmp/ssh_led_script.pid"

while true; do
  # 检测SSH连接状态
  ssh_connections=$(who | grep -c "pts/" | grep -v $$)
  
  # 有SSH连接且LED未启动时,启动脚本
  if [ $ssh_connections -gt 0 ] && [ "$led_status" = "off" ]; then
    python3 /path/to/your_led_script.py &
    echo $! > $PID_FILE
    led_status=on
    echo "SSH connected: started LED script (PID: $(cat $PID_FILE))"
  # 无SSH连接且LED已启动时,终止脚本
  elif [ $ssh_connections -eq 0 ] && [ "$led_status" = "on" ]; then
    if [ -f $PID_FILE ]; then
      PID=$(cat $PID_FILE)
      kill -2 $PID
      wait $PID 2>/dev/null
      rm -f $PID_FILE
      led_status=off
      echo "SSH disconnected: stopped LED script"
    fi
  fi
  
  # 每隔5秒检测一次,可根据需求调整间隔
  sleep 5
done

Systemd服务调试技巧

  • 查看服务状态:systemctl status ssh-led-monitor.service
  • 实时查看日志:journalctl -u ssh-led-monitor.service -f
  • 修改服务文件后重新加载:systemctl daemon-reload
  • 启动/重启服务:systemctl start ssh-led-monitor.service

额外注意事项

  • 确保Python LED脚本正确处理SIGINT信号,避免收到信号后LED残留亮灯:
    import signal
    import sys
    from blinkt import set_all, show, clear
    
    def handle_sigint(sig, frame):
        clear()
        show()
        sys.exit(0)
    
    signal.signal(signal.SIGINT, handle_sigint)
    
  • 先手动运行bash脚本验证逻辑没问题,再切换到systemd服务,降低调试难度。
  • PID文件最好放在/var/run目录(需要root权限),或者用唯一命名避免被其他进程覆盖,比如/tmp/ssh_led_monitor_$(id -u).pid。

内容的提问来源于stack exchange,提问作者Radim Lycka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:58:12