在Forever下运行的NodeJS上正常关闭UNIX套接字服务器

时间:2013-04-23 20:08:42

标签: node.js unix-socket forever

我有一个NodeJS应用程序,它设置一个UNIX套接字来公开一些进程间通信通道(某种监视内容)。 UNIX套接字文件放在os.tmpdir()文件夹中(即/tmp/app-monitor.sock)。

var net = require('net');
var server = net.createServer(...);
server.listen('/tmp/app-monitor.sock', ...);

我使用信号处理(SIGINT,SITERM等等)来正常关闭我的服务器并删除套接字文件。

function shutdown() {
    server.close(); // socket file is automatically removed here
    process.exit();
}

process.on('SIGINT', shutdown);
// and so on

我的应用程序正在运行forever start ...来监控它的生命周期。

我遇到forever restartall命令的问题。当永远在做restartall时,它使用SIGKILL来终止所有子进程。 SIGKILL无法由进程处理,因此我的应用程序在没有任何关闭过程的情况下死亡。

问题是使用SIGKILL时未删除的套接字文件。重新启动子进程后,无法启动新服务器,因为“listen调用将导致EADDRINUSE错误。”

我无法在应用启动过程中删除现有套接字文件导致'我不知道它是真正的工作套接字还是以前不干净关闭的痕迹。

所以,问题是......处理这种情况的更好方法是什么(SIGKILL和UNIX-socket服务器)?

5 个答案:

答案 0 :(得分:40)

正如其他人提到的那样,你不能做任何事情来回应SIGKILL,这通常是为什么forever(和其他人)不应该使用SIGKILL,除非在极端情况下。所以你能做的最好就是在另一个过程中清理。

我建议你在开始时清理一下。获得EADDRINUSE后,尝试连接到套接字。如果套接字连接成功,则另一台服务器正在运行,因此该实例应该退出。如果连接失败,则可以安全地取消链接套接字文件并创建一个新文件。

var fs = require('fs');
var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
    console.log('server connected');
    c.on('end', function() {
        console.log('server disconnected');
    });
    c.write('hello\r\n');
    c.pipe(c);
});

server.on('error', function (e) {
    if (e.code == 'EADDRINUSE') {
        var clientSocket = new net.Socket();
        clientSocket.on('error', function(e) { // handle error trying to talk to server
            if (e.code == 'ECONNREFUSED') {  // No other server listening
                fs.unlinkSync('/tmp/app-monitor.sock');
                server.listen('/tmp/app-monitor.sock', function() { //'listening' listener
                    console.log('server recovered');
                });
            }
        });
        clientSocket.connect({path: '/tmp/app-monitor.sock'}, function() { 
            console.log('Server running, giving up...');
            process.exit();
        });
    }
});

server.listen('/tmp/app-monitor.sock', function() { //'listening' listener
    console.log('server bound');
});

答案 1 :(得分:2)

你应该能够使用SIGTERM做你想做的事情: process.on('SIGTERM', shutdown)

答案 2 :(得分:1)

server.on('error', function (e) {
  if (e.code == 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(function () {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});

http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback

<强> UPD

你无法处理SIGKILL,那么你必须清理套接字手册

此示例可以正常使用

var fs = require('fs');
var net = require('net');
var server = net.createServer(function(c) {});
server.listen('./app-monitor.sock', function() {
  console.log('server bound');
});

server.on('error', function (e) {
  if (e.code == 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(function () {
      fs.unlink('./app-monitor.sock');
    }, 1000);
  }
});

答案 3 :(得分:1)

由于您无法处理SIGKILL而您想永久使用(使用SIGKILL),因此您必须使用解决方法。

例如,首先发送信号以关闭服务器,然后永远重启:

kill -s SIGUSR1 $pid
# $pid contains the pid of your node process, or use
# killall -SIGUSR1 node

sleep 2
forever restart test.js

在你的js句柄中SIGUSR1:

process.on('SIGUSR1', gracefullyShutdownMyServer);

答案 4 :(得分:0)

你必须选择

  1. 将SIGKILL更改为永久监视器中的另一个信号,以便在应用程序中处理
  2. 在这种情况下使用fs.unlink
  3. 处理您的应用
  4. 永远停止使用