网络中断恢复后,如何自动重启树莓派上的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.targetRestart=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
相关产品推荐
相关产品推荐

