如何在Node脚本崩溃后自动重启脚本或其init.d服务?
让Raspbian上的Node.js开机服务崩溃后自动重启
最近我在运行Raspbian系统的树莓派上部署了一个Node.js脚本,已经把它做成/etc/init.d下的开机自启服务,通电就能自动运行,本来挺省心的。但遇到个头疼的问题:要是脚本崩溃导致Node进程退出,这个开机服务不会自动重启,每次都得手动去启动,实在麻烦。下面是我当前用的服务代码:
#! /bin/sh ### BEGIN INIT INFO # Provides: MyScriptService # Required-Start: $all # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts my node.js script. ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin . /lib/init/vars.sh . /lib/lsb/init-functions case "$1" in start) log_begin_msg "Starting my script" node /home/pi/myscript.js log_end_msg $? exit 0 ;; stop) log_begin_msg "Stopping my script" log_end_msg $? exit 0 ;; *) exit 1 ;; esac
后来我折腾了一阵,通过Node自身的方式解决了这个问题,这里把可行的方案分享给大家:
方案1:在Node脚本内加守护重启逻辑
直接在你的myscript.js里添加一段代码,让脚本在崩溃后自动重启。这种方式不用改系统服务脚本,只需要修改Node代码就行,我自己用的就是这个方案:
const { spawn } = require('child_process'); let childProcess; function startScript() { // 启动子进程运行当前脚本,标记为子进程 childProcess = spawn(process.argv[0], [__filename], { stdio: 'inherit', env: { ...process.env, IS_CHILD: 'true' } }); // 监听子进程退出事件 childProcess.on('exit', (exitCode) => { // 如果是非正常退出(退出码不为0),就延迟1秒重启 if (exitCode !== 0) { console.log(`脚本崩溃,退出码${exitCode},1秒后重启...`); setTimeout(startScript, 1000); } }); } // 如果是父进程,就启动子进程;如果是子进程,就运行原有业务逻辑 if (!process.env.IS_CHILD) { startScript(); } else { // 这里放你原来的Node.js业务代码 // 比如你的HTTP服务、传感器读取逻辑等等 // ... }
方案2:修改init.d服务脚本,让它循环重启进程
如果你不想改Node脚本,也可以直接修改/etc/init.d里的服务脚本,让它在启动Node进程后持续监控,一旦进程退出就重新启动。修改后的start部分代码如下:
start) log_begin_msg "Starting my script" # 循环检查,进程退出就重启 while true; do node /home/pi/myscript.js log_msg "脚本崩溃,退出码 $?,正在重启..." sleep 1 # 延迟1秒,避免频繁重启 done log_end_msg $? exit 0 ;;
另外,原来的stop部分没有实际停止进程的逻辑,得补上,不然没法正常停止服务:
stop) log_begin_msg "Stopping my script" # 通过进程名查找并终止Node进程 pkill -f "node /home/pi/myscript.js" log_end_msg $? exit 0 ;;
这两种方案都能实现进程崩溃后自动重启的效果,亲测在Raspbian上有效。
内容的提问来源于stack exchange,提问作者Mason
相关产品推荐
相关产品推荐

