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

如何实现通过/etc/init.d脚本正常停止作为服务运行的Node.js服务器

How to Gracefully Stop a Node.js Connect Server via init.d Without kill/killall

Problem Statement

I've set up a small Node.js server as a boot service using an /etc/init.d/lightserver script. Currently, the stop action is empty, and I want to be able to run /etc/init.d/lightserver stop to shut down the server properly without using kill or killall commands. Here's my current init.d script:

# Actions
case "$1" in
start)
# START
/usr/bin/lightserver
;;
stop)
# STOP
;;
restart)
# RESTART
;;
esac
exit 0

And my Node.js server code:

var i = 0;
var connect = require('connect');
var sleep = require('sleep');
var exec = require('child_process').exec;
var j = 1;
var server = connect().
use(function(req, res) {
i++;
res.write('Hello World! ' + i);
res.end();
let code = 83028 + j;
j = 1 - j;
exec("./433Utils/RPi_utils/codesend " + code, function(error, stdout, stderr) {
console.log(stdout);
});
}).listen(64084);
console.log("Server has started and is listening to http://localhost:64084/");

Solution

Great question! The cleanest way to handle this without kill/killall is to add a local-only shutdown endpoint to your Node.js server, then update the init.d script to trigger this endpoint via a simple HTTP request. Here's how to do it step by step:

Step 1: Update Your Node.js Server Code

Add a dedicated middleware to handle shutdown requests, restricted to localhost for security. We'll use server.close() to gracefully stop accepting new connections and wait for in-progress requests to finish before exiting:

var i = 0;
var connect = require('connect');
var sleep = require('sleep');
var exec = require('child_process').exec;
var j = 1;

var server = connect()
  // Shutdown handler (must come first to catch the /stop request)
  .use(function(req, res, next) {
    // Allow only localhost to trigger shutdown (covers IPv4 and IPv6)
    const isLocal = req.connection.remoteAddress === '127.0.0.1' || req.connection.remoteAddress === '::1';
    if (req.url === '/stop' && isLocal) {
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Server is shutting down gracefully...');
      
      // Close the server and exit once all connections are done
      server.close(function() {
        console.log('Server stopped successfully');
        process.exit(0);
      });
      return;
    }
    next(); // Pass regular requests to your main handler
  })
  .use(function(req, res) {
    i++;
    res.write('Hello World! ' + i);
    res.end();
    let code = 83028 + j;
    j = 1 - j;
    exec("./433Utils/RPi_utils/codesend " + code, function(error, stdout, stderr) {
      console.log(stdout);
    });
  })
  .listen(64084);

console.log("Server has started and is listening to http://localhost:64084/");

Step 2: Update Your init.d Script

Modify the stop block to call the /stop endpoint using curl (if curl isn't installed, use wget as an alternative):

# Actions
case "$1" in
start)
# START
/usr/bin/lightserver
;;
stop)
# STOP
# Trigger shutdown via local HTTP request
curl -s http://localhost:64084/stop > /dev/null
# Uncomment below if curl isn't available:
# wget -q -O - http://localhost:64084/stop > /dev/null
;;
restart)
# RESTART
$0 stop
sleep 2 # Give the server time to finish ongoing requests
$0 start
;;
esac
exit 0

Why This Works

  • Security: The /stop endpoint is locked to localhost, so external clients can't shut down your server accidentally or maliciously.
  • Graceful Shutdown: server.close() ensures all active requests are completed before the server exits, avoiding broken connections or incomplete operations.
  • No Kill Commands: The init.d script uses a standard HTTP request instead of low-level process signals, meeting your requirement perfectly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:51:09