pm2-gui/lib/daemon.js

153 lines
3.6 KiB
JavaScript

var chalk = require('chalk'),
path = require('path'),
fs = require('fs'),
async = require('async'),
cp = require('child_process'),
fork = cp.fork,
spawn = cp.spawn,
Monitor = require('./monitor'),
Log = require('./util/log');
var processDirname = path.resolve(__dirname, '../'),
confFile = './pm2-gui.ini',
cmd = 'start';
if (process.argv.length > 2) {
cmd = process.argv[2];
}
if (process.argv.length > 3) {
confFile = process.argv[3];
}
confFile = path.resolve(processDirname, confFile);
if (!fs.existsSync(confFile)) {
console.error(chalk.bold(confFile), chalk.red('does not exist!'));
return process.exit(0);
}
var monitor = Monitor({
confFile: confFile
}),
daemonize = monitor.options.daemonize && cmd != 'mon';
Log(monitor.options.log);
var pidfile = path.resolve(processDirname, './pm2-gui.pid');
var Daemon = {
restarts: 0,
init: function (next) {
process.on('SIGTERM', Daemon.stop);
process.on('SIGINT', Daemon.stop);
process.on('SIGHUP', Daemon.restart);
next && next();
},
start: function (next) {
Daemon.worker = Daemon.fork();
next && next();
},
restart: function () {
console.info('Restarting...');
Daemon.kill();
Daemon.start();
},
stop: function () {
console.info('Stopping...');
Daemon.kill();
daemonize && fs.existsSync(pidfile) && fs.unlinkSync(pidfile);
},
kill: function () {
if (Daemon.worker) {
Daemon.worker.suicide = true;
Daemon.worker.kill();
}
},
fork: function () {
console.info('Forking slave...');
var worker = fork(path.resolve(processDirname, 'pm2-gui.js'), [cmd, confFile, '--color'], {
silent: daemonize,
env: process.env
});
worker.on('exit', function (code, signal) {
if (code != 0) {
if (Daemon.restarts < 10) {
Daemon.restarts++;
setTimeout(function () {
Daemon.restarts--;
}, 20000);
} else {
console.error(Daemon.restarts + ' restarts in 20 seconds, view the logs to investigate the crash problem.');
return process.exit(0);
}
}
if (!(worker.suicide || code === 0)) {
setTimeout(Daemon.fork, 3000);
}
});
worker.on('message', function (message) {
if (typeof message == 'object' && message.action)
if (message.action == 'restart') {
Daemon.restart();
}
});
var logDir = monitor.options.log.dir,
stdout = 'pm2-gui.out',
stderr = 'pm2-gui.err';
if (!logDir) {
logDir = './logs';
}
logDir = path.resolve(processDirname, logDir);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
if (daemonize) {
stdout = fs.createWriteStream(path.join(logDir, stdout));
stderr = fs.createWriteStream(path.join(logDir, stderr));
worker.stdout.pipe(stdout);
worker.stderr.pipe(stderr);
fs.writeFile(pidfile, worker.pid);
}
return worker;
},
daemonize: function () {
if (process.env.daemonized) {
console.info('Daemonized with pid [' + process.pid + '].');
return;
}
console.info('Spawning daemon...');
var args = [].concat(process.argv);
args.shift();
var env = process.env;
env.daemonized = true;
var child = spawn(process.execPath, args, {
env: env,
detached: false,
cwd: processDirname,
stdio: ['ignore', process.stdout, process.stderr]
});
child.unref();
process.exit();
}
};
if (daemonize) {
Daemon.daemonize();
}
process.title = 'pm2-gui daemon';
async.series([
Daemon.init,
Daemon.start
], function (err) {
if (err) {
console.error(err.stack);
}
});