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

网络中断恢复后,如何自动重启树莓派上的systemd服务?

解决网络恢复后自动重启Node.js Express服务的方案

遇到这种情况太常见了——很多依赖网络的服务在接口断开再恢复后,会因为绑定的套接字失效而停止监听,但进程本身还在运行,systemd默认不会主动重启它。下面给你几个实用的解决方案,按从简单到进阶的顺序排列:

方案1:优化systemd单元文件的重启策略与网络依赖

先从修改现有的systemd服务文件入手,这是最直接的方式:

  • 打开你的服务单元文件(比如/etc/systemd/system/your-express-app.service)
  • 在[Service]段添加或修改以下配置:
    # 只要进程退出就重启,包括正常退出(如果应用因网络问题主动退出的话)
    Restart=always
    # 重启前等待3秒,避免频繁重启
    RestartSec=3
    # 确保服务在网络完全就绪后启动(避免启动时网络还没好)
    After=network-online.target
    Wants=network-online.target
    
    不过这里有个局限:如果应用进程没退出,只是停止监听,Restart=always不会触发。这时候可以搭配下面的方案一起用。

方案2:添加网络状态监控的辅助服务

可以创建一个独立的systemd服务,用来监控网络连通性,当网络恢复时自动重启你的Express服务:

  • 创建一个监控脚本/usr/local/bin/check-network-restart-app.sh,内容如下:
    #!/bin/bash
    # 监控网络连通性,这里用ping网关为例,你可以换成你的局域网IP或外部地址
    GATEWAY=$(ip route | grep default | awk '{print $3}')
    while true; do
        if ping -c 1 -W 2 $GATEWAY > /dev/null 2>&1; then
            # 网络恢复,检查Express服务是否在监听(假设监听3000端口)
            if ! ss -tulpn | grep -q ":3000.*node"; then
                systemctl restart your-express-app.service
                echo "$(date): Network restored, restarted Express service" >> /var/log/network-restart.log
            fi
            # 网络正常时每隔60秒检查一次
            sleep 60
        else
            # 网络断开时每隔10秒检查一次
            sleep 10
        fi
    done
    
  • 给脚本加执行权限:chmod +x /usr/local/bin/check-network-restart-app.sh
  • 创建对应的systemd服务文件/etc/systemd/system/network-monitor.service:
    [Unit]
    Description=Monitor network status and restart Express app on recovery
    After=network.target
    
    [Service]
    ExecStart=/usr/local/bin/check-network-restart-app.sh
    Restart=always
    User=root # 或者运行你的Express服务的用户
    
    [Install]
    WantedBy=multi-user.target
    
  • 启用并启动这个监控服务:
    systemctl daemon-reload
    systemctl enable --now network-monitor.service
    

方案3:修改Node.js应用,处理网络变化事件

从应用层面解决问题是最彻底的:让Express应用监听网络接口的变化,当接口恢复时重新绑定端口。你可以在应用代码中添加类似以下的逻辑:

const os = require('os');
const net = require('net');
const express = require('express');
const app = express();

// 存储服务器实例
let server;

function startServer() {
  server = app.listen(3000, '0.0.0.0', () => {
    console.log('Server listening on port 3000');
  });

  server.on('error', (err) => {
    console.error('Server error:', err);
    if (err.code === 'EADDRINUSE') {
      console.log('Port in use, retrying in 5 seconds...');
      setTimeout(startServer, 5000);
    }
  });
}

// 监听网络接口变化
function monitorNetwork() {
  let previousInterfaces = os.networkInterfaces();

  setInterval(() => {
    const currentInterfaces = os.networkInterfaces();
    // 比较接口变化(简化版,你可以更精确地检测特定接口的状态)
    const isChanged = JSON.stringify(previousInterfaces) !== JSON.stringify(currentInterfaces);
    if (isChanged) {
      console.log('Network interfaces changed, restarting server...');
      if (server) {
        server.close(() => {
          startServer();
        });
      }
      previousInterfaces = currentInterfaces;
    }
  }, 10000); // 每10秒检查一次
}

// 启动服务和监控
startServer();
monitorNetwork();

这个方法不需要依赖外部脚本,直接在应用内部处理网络变化,自动重启监听。

验证测试

不管用哪个方案,都建议手动测试一下:

  • 断开树莓派的网络(比如拔网线或禁用WiFi)
  • 等待1分钟左右,恢复网络
  • 检查服务状态:systemctl status your-express-app.service,或者访问应用的端口确认是否正常

内容的提问来源于stack exchange,提问作者Giovanni Bauermeister

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:17:29