diff --git a/bin/pm2 b/bin/pm2 index 88615adb..614edb48 100755 --- a/bin/pm2 +++ b/bin/pm2 @@ -366,6 +366,15 @@ commander.command('flush') CLI.flush(); })); +// +// Reload all logs +// +commander.command('reloadLogs') + .description('reload all logs') + .action(function() { + CLI.reloadLogs(); + }); + // // Log streaming // diff --git a/lib/CLI.js b/lib/CLI.js index 6a372262..1522d3f0 100644 --- a/lib/CLI.js +++ b/lib/CLI.js @@ -66,7 +66,7 @@ CLI.startFile = function(script) { appConf['one_launch_only'] = cst.ONE_LAUNCH_STATUS; // if (appConf['exec_mode'] == 'cluster_mode' && process.version.match(/0.10/)) { - // console.log(cst.PREFIX_MSG_ERR + ' [Warning], you\'re using the 0.10.x node version, it\'s prefered that you switch to fork mode by adding the -x parameter.'); + // printOut(cst.PREFIX_MSG_ERR + ' [Warning], you\'re using the 0.10.x node version, it\'s prefered that you switch to fork mode by adding the -x parameter.'); // } // Script arguments @@ -76,7 +76,7 @@ CLI.startFile = function(script) { if (commander.write) { var dst_path = path.join(process.env.PWD, path.basename(script, '.js') + '-pm2.json'); - console.log(cst.PREFIX_MSG + 'Writing configuration to ', dst_path); + printOut(cst.PREFIX_MSG + 'Writing configuration to ', dst_path); fs.writeFileSync(dst_path, JSON.stringify(appConf)); } @@ -89,7 +89,7 @@ CLI.startFile = function(script) { exec[0].pm2_env.status == cst.STOPPING_STATUS)) { var app_name = exec[0].pm2_env.name; Satan.executeRemote('restartProcessName', app_name, function(err, list) { - console.log(cst.PREFIX_MSG + 'Process successfully started'); + printOut(cst.PREFIX_MSG + 'Process successfully started'); return speedList(); }); return false; @@ -100,7 +100,7 @@ CLI.startFile = function(script) { } Satan.executeRemote('prepare', resolvePaths(appConf), function() { - console.log(cst.PREFIX_MSG + 'Process launched'); + printOut(cst.PREFIX_MSG + 'Process launched'); speedList(); }); return false; @@ -132,13 +132,13 @@ CLI.actionFromJson = function(action, file, jsonVia) { Satan.executeRemote(action, name, function(err, list) { if (err) console.error(err); - console.log(cst.PREFIX_MSG + 'Stopping process by name ' + name); + printOut(cst.PREFIX_MSG + 'Stopping process by name ' + name); next(); }); }, function(err) { if (err) { - console.log(err); + printOut(err); return exitCli(cst.ERROR_EXIT); } @@ -188,7 +188,7 @@ CLI.startFromJson = function(cmd,jsonVia) { function launchApp(appPaths){ Satan.executeRemote('prepare', appPaths, function() { - console.log(cst.PREFIX_MSG + 'Process launched'); + printOut(cst.PREFIX_MSG + 'Process launched'); nextApp(); }); } @@ -239,19 +239,19 @@ CLI.startup = function(platform) { script = script.toString().replace(/%NODE_PATH%/g, p.dirname(process.execPath)); script = script.toString().replace(/%USER%/g, user); - console.log(cst.PREFIX_MSG + 'Generating system init script in ' + INIT_SCRIPT); + printOut(cst.PREFIX_MSG + 'Generating system init script in ' + INIT_SCRIPT); fs.writeFileSync(INIT_SCRIPT, script); if (fs.existsSync(INIT_SCRIPT) == false) { - console.log(script); - console.log(cst.PREFIX_MSG_ERR + ' There is a problem when trying to write file : ' + INIT_SCRIPT); + printOut(script); + printOut(cst.PREFIX_MSG_ERR + ' There is a problem when trying to write file : ' + INIT_SCRIPT); exitCli(cst.ERROR_EXIT); } var cmd; - console.log(cst.PREFIX_MSG + 'Making script booting at startup...'); + printOut(cst.PREFIX_MSG + 'Making script booting at startup...'); if (platform == 'systemd') { cmd = [ @@ -262,27 +262,27 @@ CLI.startup = function(platform) { 'systemctl start pm2' ].join(' && '); - console.log(cst.PREFIX_MSG + '-systemd- Using the command %s', cmd); + printOut(cst.PREFIX_MSG + '-systemd- Using the command %s', cmd); } else if (platform == 'centos' || platform == 'redhat' || platform == 'amazon') { cmd = 'chmod +x ' + INIT_SCRIPT + '; chkconfig --add ' + p.basename(INIT_SCRIPT); - console.log(cst.PREFIX_MSG + '-centos- Using the command %s', cmd); + printOut(cst.PREFIX_MSG + '-centos- Using the command %s', cmd); fs.openSync('/var/lock/subsys/pm2-init.sh', 'w'); - console.log('/var/lock/subsys/pm2-init.sh lockfile has been added'); + printOut('/var/lock/subsys/pm2-init.sh lockfile has been added'); } else { cmd = 'chmod +x ' + INIT_SCRIPT + '; update-rc.d ' + p.basename(INIT_SCRIPT) + ' defaults'; - console.log(cst.PREFIX_MSG + '-ubuntu- Using the command %s', cmd); + printOut(cst.PREFIX_MSG + '-ubuntu- Using the command %s', cmd); } exec(cmd, function(err, stdo, stde) { if (err) { console.error(err); - console.log('----- Are you sure you use the right platform command line option ? centos / redhat, amazon, ubuntu or systemd?'); + printOut('----- Are you sure you use the right platform command line option ? centos / redhat, amazon, ubuntu or systemd?'); exitCli(cst.ERROR_EXIT); } - console.log(stdo); - console.log(cst.PREFIX_MSG + 'Done.'); + printOut(stdo); + printOut(cst.PREFIX_MSG + 'Done.'); exitCli(cst.SUCCESS_EXIT); }); }; @@ -290,9 +290,9 @@ CLI.startup = function(platform) { CLI.interact = function(secret_key, public_key, machine_name) { InteractorDaemonizer.launchOrAttach(secret_key, public_key, machine_name, function(status) { if (status == false) - console.log('Interactor already launched'); + printOut('Interactor already launched'); else - console.log('Successfully launched interactor'); + printOut('Successfully launched interactor'); exitCli(cst.SUCCESS_EXIT); }); }; @@ -309,7 +309,7 @@ CLI.killInteract = function(secret_key, machine_name) { console.error(err); return exitCli(cst.ERROR_EXIT); } - console.log('Interactor successfully killed'); + printOut('Interactor successfully killed'); return exitCli(cst.SUCCESS_EXIT); }); }); @@ -323,7 +323,7 @@ CLI.ping = function() { console.error(err); exitCli(cst.ERROR_EXIT); } - console.log(res); + printOut(res); exitCli(cst.SUCCESS_EXIT); }); }; @@ -342,7 +342,7 @@ CLI.resurrect = function() { if (err) console.error(cst.PREFIX_MSG_ERR + ' Process %s not launched - (script missing)', apps[0].pm_exec_path); else - console.log(cst.PREFIX_MSG + 'Process %s launched', apps[0].pm_exec_path); + printOut(cst.PREFIX_MSG + 'Process %s launched', apps[0].pm_exec_path); apps.shift(); return ex(apps); }); @@ -387,7 +387,7 @@ CLI.web = function() { name : 'Pm2Http' + cst.WEB_INTERFACE, exec_mode : 'fork_mode' }), function() { - console.log(cst.PREFIX_MSG + 'Process launched'); + printOut(cst.PREFIX_MSG + 'Process launched'); speedList(); }); }; @@ -414,12 +414,12 @@ CLI.reload = function (reload_method) { console.error('Error : ' + err); exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Process %s succesfully reloaded', proc.pm2_env.name); + printOut(cst.PREFIX_MSG + 'Process %s succesfully reloaded', proc.pm2_env.name); return next(); }); return false; }, function(err) { - console.log(cst.PREFIX_MSG + 'All processes reloaded'); + printOut(cst.PREFIX_MSG + 'All processes reloaded'); return setTimeout(speedList, 500); }); }); @@ -431,7 +431,7 @@ CLI.reload = function (reload_method) { * @param {string} reload_method RPC method to hit (can be reloadProcessId or softReloadProcessId) */ CLI.reloadProcessName = function (process_name, reload_method) { - console.log(cst.PREFIX_MSG + 'Reloading process by name %s', process_name); + printOut(cst.PREFIX_MSG + 'Reloading process by name %s', process_name); getProcessByName(process_name, function(err, processes) { @@ -446,12 +446,12 @@ CLI.reloadProcessName = function (process_name, reload_method) { console.error('Error : ' + err); exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Process %s succesfully reloaded', proc.pm2_env.name); + printOut(cst.PREFIX_MSG + 'Process %s succesfully reloaded', proc.pm2_env.name); return next(); }); return false; }, function(err) { - console.log(cst.PREFIX_MSG + 'All processes reloaded'); + printOut(cst.PREFIX_MSG + 'All processes reloaded'); return setTimeout(speedList, 500); }); }); @@ -464,7 +464,7 @@ CLI.restartProcessByName = function(pm2_name) { return exitCli(cst.ERROR_EXIT); } UX.processing.stop(); - console.log(cst.PREFIX_MSG + 'Process ' + pm2_name + ' restarted'); + printOut(cst.PREFIX_MSG + 'Process ' + pm2_name + ' restarted'); speedList(); }); }; @@ -476,7 +476,7 @@ CLI.restartProcessById = function(pm2_id) { return exitCli(cst.ERROR_EXIT); } UX.processing.stop(); - console.log(cst.PREFIX_MSG + 'Process ' + pm2_id + ' restarted'); + printOut(cst.PREFIX_MSG + 'Process ' + pm2_id + ' restarted'); speedList(); }); }; @@ -497,7 +497,7 @@ CLI.restartAll = function() { var proc = processes[0]; if (proc == null) { - console.log(cst.PREFIX_MSG + 'Process restarted...'); + printOut(cst.PREFIX_MSG + 'Process restarted...'); return setTimeout(speedList, 1000); } Satan.executeRemote('restartProcessId', proc.pm2_env.pm_id, function(err, res) { @@ -505,7 +505,7 @@ CLI.restartAll = function() { printError(err); return exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Process ' + proc.pm2_env.name + ' restarted'); + printOut(cst.PREFIX_MSG + 'Process ' + proc.pm2_env.name + ' restarted'); processes.shift(); return rec(processes); }); @@ -531,7 +531,7 @@ CLI.deleteProcess = function(process_name, jsonVia) { if (process_name.indexOf('.json') > 0) return CLI.actionFromJson('deleteProcessName', process_name, 'file'); else if (process_name == 'all') { - console.log(cst.PREFIX_MSG + 'Stopping and deleting all processes'); + printOut(cst.PREFIX_MSG + 'Stopping and deleting all processes'); Satan.executeRemote('deleteAll', {}, function(err, list) { if (err) { printError(err); @@ -542,7 +542,7 @@ CLI.deleteProcess = function(process_name, jsonVia) { }); } else if (!isNaN(parseInt(process_name))) { - console.log('Stopping and deleting process by id : %s', process_name); + printOut('Stopping and deleting process by id : %s', process_name); Satan.executeRemote('deleteProcessId', process_name, function(err, list) { if (err) { printError(err); @@ -553,7 +553,7 @@ CLI.deleteProcess = function(process_name, jsonVia) { }); } else { - console.log(cst.PREFIX_MSG + 'Stopping and deleting process by name %s', process_name); + printOut(cst.PREFIX_MSG + 'Stopping and deleting process by name %s', process_name); Satan.executeRemote('deleteProcessName', process_name, function(err, list) { if (err) { printError(err); @@ -571,7 +571,7 @@ CLI.stopProcessName = function(name) { printError(err); return exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Stopping process by name ' + name); + printOut(cst.PREFIX_MSG + 'Stopping process by name ' + name); UX.processing.stop(); speedList(); }); @@ -583,7 +583,7 @@ CLI.stopId = function(pm2_id) { printError(err); return exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + ' Process stopped'); + printOut(cst.PREFIX_MSG + ' Process stopped'); UX.processing.stop(); speedList(); }); @@ -611,15 +611,15 @@ CLI.jlist = function(debug) { exitCli(cst.ERROR_EXIT); } if (debug) - console.log(list); + printOut(list); else - console.log(JSON.stringify(list)); + printOut(JSON.stringify(list)); exitCli(cst.SUCCESS_EXIT); }); }; CLI.flush = function() { - console.log(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH); + printOut(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH); fs.openSync(cst.PM2_LOG_FILE_PATH, 'w'); Satan.executeRemote('getMonitorData', {}, function(err, list) { @@ -628,9 +628,9 @@ CLI.flush = function() { exitCli(cst.ERROR_EXIT); } list.forEach(function(l) { - console.log(cst.PREFIX_MSG + 'Flushing'); - console.log(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path); - console.log(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path); + printOut(cst.PREFIX_MSG + 'Flushing'); + printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path); + printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path); fs.openSync(l.pm2_env.pm_out_log_path, 'w'); fs.openSync(l.pm2_env.pm_err_log_path, 'w'); @@ -639,6 +639,15 @@ CLI.flush = function() { }); }; +CLI.reloadLogs = function() { + printOut('Reloading all logs...'); + Satan.executeRemote('reloadLogs', {}, function(err, logs) { + if (err) printError(err); + printOut('All logs reloaded'); + exitCli(cst.SUCCESS_EXIT); + }); +}; + CLI.sendSignalToProcessName = function(signal, process_name) { Satan.executeRemote('sendSignalToProcessName', { signal : signal, @@ -648,7 +657,7 @@ CLI.sendSignalToProcessName = function(signal, process_name) { printError(err); exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Succesfully sent signal %s to process name %s', signal, process_name); + printOut(cst.PREFIX_MSG + 'Succesfully sent signal %s to process name %s', signal, process_name); UX.processing.stop(); speedList(); }); @@ -663,7 +672,7 @@ CLI.sendSignalToProcessId = function(signal, process_id) { printError(err); exitCli(cst.ERROR_EXIT); } - console.log(cst.PREFIX_MSG + 'Succesfully sent signal %s to process id %s', signal, process_id); + printOut(cst.PREFIX_MSG + 'Succesfully sent signal %s to process id %s', signal, process_id); UX.processing.stop(); speedList(); }); @@ -676,7 +685,7 @@ CLI.monit = function() { exitCli(cst.ERROR_EXIT); } if (Object.keys(list).length == 0) { - console.log(cst.PREFIX_MSG + 'No online process to monitor'); + printOut(cst.PREFIX_MSG + 'No online process to monitor'); exitCli(cst.ERROR_EXIT); } @@ -707,7 +716,7 @@ CLI.streamLogs = function(id) { exitCli(cst.ERROR_EXIT); } - console.log('########### Starting streaming logs for [%s] process', id || 'all'); + printOut('########### Starting streaming logs for [%s] process', id || 'all'); list.forEach(function(proc) { if ((!id || (id && !isNaN(parseInt(id)) && proc.pm_id == id)) || (!id || (id && isNaN(parseInt(id)) && proc.pm2_env.name == id))) { @@ -726,14 +735,36 @@ CLI.streamLogs = function(id) { }; CLI.killDaemon = function() { - Satan.killDaemon(function(err, res) { + printOut('Killing pm2...'); + + Satan.executeRemote('getMonitorData', {}, function(err, list) { if (err) { - printError(err); + console.error('Error retrieving process list: ' + err); exitCli(cst.ERROR_EXIT); } - console.info('Daemon killed'); - exitCli(cst.SUCCESS_EXIT); + + async.eachLimit(list, 1, function(proc, next) { + Satan.executeRemote('deleteProcessId', proc.pm2_env.pm_id, function(err, res) { + if (err) + printError('Error : ' + err); + printOut('Process %s stopped', proc.pm2_env.name); + return next(); + }); + return false; + }, function(err) { + printOut('All processes stopped'); + Satan.killDaemon(function(err, res) { + if (err) { + printError(err); + exitCli(cst.ERROR_EXIT); + } + console.info('PM2 stopped'); + exitCli(cst.SUCCESS_EXIT); + }); + }); + }); + }; @@ -765,8 +796,8 @@ function speedList() { return exitCli(cst.SUCCESS_EXIT); } else { - console.log('--no-daemon option enabled = do not exit pm2 CLI'); - console.log('PM2 dameon PID = %s', fs.readFileSync(cst.PM2_PID_FILE_PATH)); + printOut('--no-daemon option enabled = do not exit pm2 CLI'); + printOut('PM2 dameon PID = %s', fs.readFileSync(cst.PM2_PID_FILE_PATH)); return Log.stream(cst.PM2_LOG_FILE_PATH); } }); @@ -778,9 +809,7 @@ function printError(msg) { return console.error(msg); }; -function printOut(msg) { - console.log(msg); -}; +var printOut = console.log; function exitCli(code) { Satan.client.sock.close(); diff --git a/lib/God/ActionMethods.js b/lib/God/ActionMethods.js index 582a1a36..a76c536f 100644 --- a/lib/God/ActionMethods.js +++ b/lib/God/ActionMethods.js @@ -435,31 +435,39 @@ module.exports = function(God) { God.restartWatch = function(method, value, fn) { var env; - if(method == 'restartProcessId') { + if (method == 'restartProcessId') { env = God.clusters_db[value]; } else if(method == 'restartProcessName') { env = God.clusters_db[God.findByName(value)]; } - if(env) { - - if(!env.watch) + if (env) { + if (!env.watch) require('../Watcher').watch(env.pm2_env); else require('../Watcher').close(env.pm2_env.pm_id); env.pm2_env.watch = !env.pm2_env.watch; - } + }; - } + God.reloadLogs = function(opts, cb) { + console.log('Reloading logs...'); + var processIds = Object.keys(God.clusters_db); + + processIds.forEach(function (id) { + var cluster = God.clusters_db[id]; + cluster.send({type:'log:reload'}); + console.log('Reloading logs for process id %d', id); + }); + return cb(null, {}); + }; /** * Send Message to Process by id or name */ God.msgProcess = function(opts, cb) { - var msg = opts.msg || {}; if ('id' in opts) { diff --git a/lib/Satan.js b/lib/Satan.js index d4522046..09eb9dd2 100644 --- a/lib/Satan.js +++ b/lib/Satan.js @@ -60,7 +60,6 @@ Satan.start = function(noDaemonMode) { * */ Satan.processStateHandler = function(God) { - function gracefullExit() { console.log('pm2 has been killed by signal'); try { @@ -69,15 +68,6 @@ Satan.processStateHandler = function(God) { process.exit(0); } - function reloadLogs() { - console.log('Reloading logs...'); - var processIds = Object.keys(God.clusters_db); - processIds.forEach(function (id) { - var cluster = God.clusters_db[id]; - cluster.send({type:'log:reload'}) - }); - } - try { fs.writeFileSync(cst.PM2_PID_FILE_PATH, process.pid); } catch(e){} @@ -85,7 +75,9 @@ Satan.processStateHandler = function(God) { process.on('SIGTERM', gracefullExit); process.on('SIGINT', gracefullExit); process.on('SIGQUIT', gracefullExit); - process.on('SIGUSR2', reloadLogs); + process.on('SIGUSR2', function() { + God.reloadLogs({}, function() {}); + }); }; /** @@ -161,7 +153,7 @@ Satan.remoteWrapper = function() { sendSignalToProcessId : God.sendSignalToProcessId, sendSignalToProcessName : God.sendSignalToProcessName, getVersion : God.getVersion, - + reloadLogs : God.reloadLogs, stopWatch : God.stopWatch, restartWatch : God.restartWatch }); diff --git a/package.json b/package.json index 12059531..4aa58e33 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "description": "Modern CLI process manager for Node apps with a builtin load-balancer", "main": "index.js", "scripts": { - "test": "bash ./test/cli.sh && bash ./test/json_file.sh && bash ./test/harmony.sh && bash ./test/reload.sh && bash ./test/right-exit-code.sh && bash ./test/gracefulReload.sh && bash ./test/cli2.sh && bash ./test/misc.sh && bash ./test/watch.sh && bash ./test/fork.sh && bash ./test/infinite_loop.sh && NODE_ENV=test ./node_modules/mocha/bin/mocha test" + "test": "bash ./test/cli.sh && bash ./test/json_file.sh && bash ./test/harmony.sh && bash ./test/reload.sh && bash ./test/right-exit-code.sh && bash ./test/log-reload.sh && bash ./test/gracefulReload.sh && bash ./test/cli2.sh && bash ./test/misc.sh && bash ./test/watch.sh && bash ./test/fork.sh && bash ./test/infinite_loop.sh && NODE_ENV=test ./node_modules/mocha/bin/mocha test" }, "keywords": [ "cli", @@ -68,6 +68,11 @@ "pm2", "harmony", "node-pm2", + "production", + "vitalsigns", + "pm2.io", + "ghost", + "ghost production", "monitoring", "process manager", "forever", diff --git a/test/log-reload.sh b/test/log-reload.sh new file mode 100644 index 00000000..261adedf --- /dev/null +++ b/test/log-reload.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +SRC=$(cd $(dirname "$0"); pwd) +source "${SRC}/include.sh" + +cd $file_path + +echo -e "\033[1mRunning tests:\033[0m" + +$pm2 kill + +>out-rel.log + +$pm2 start echo.js -o out-rel.log --merge-logs + +$pm2 reloadLogs + +sleep 1 + +grep "Reloading log..." out-rel.log + +spec "Should have started the reloading action"