我有一个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服务器)?
答案 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)
你必须选择