123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- /**
- * Copyright 2013-2022 the PM2 project authors. All rights reserved.
- * Use of this source code is governed by a license that
- * can be found in the LICENSE file.
- */
- 'use strict';
- /**
- * @file Utilities for PM2
- * @author Alexandre Strzelewicz <as@unitech.io>
- * @project PM2
- */
- var p = require('path');
- var treekill = require('../TreeKill');
- var cst = require('../../constants.js');
- /**
- * Description
- * @method exports
- * @param {} God
- * @return
- */
- module.exports = function(God) {
- /**
- * Description
- * @method logAndGenerateError
- * @param {} err
- * @return NewExpression
- */
- God.logAndGenerateError = function(err) {
- // Is an Error object
- if (err instanceof Error) {
- console.trace(err);
- return err;
- }
- // Is a JSON or simple string
- console.error(err);
- return new Error(err);
- };
- /**
- * Utility functions
- * @method getProcesses
- * @return MemberExpression
- */
- God.getProcesses = function() {
- return God.clusters_db;
- };
- God.getFormatedProcess = function getFormatedProcesses(id) {
- if (God.clusters_db[id])
- return {
- pid : God.clusters_db[id].process.pid,
- name : God.clusters_db[id].pm2_env.name,
- pm2_env : God.clusters_db[id].pm2_env,
- pm_id : God.clusters_db[id].pm2_env.pm_id
- };
- return {};
- };
- /**
- * Get formated processes
- * @method getFormatedProcesses
- * @return {Array} formated processes
- */
- God.getFormatedProcesses = function getFormatedProcesses() {
- var keys = Object.keys(God.clusters_db);
- var arr = new Array();
- var kl = keys.length;
- for (var i = 0; i < kl; i++) {
- var key = keys[i];
- if (!God.clusters_db[key]) continue;
- // Avoid _old type pm_ids
- if (isNaN(God.clusters_db[key].pm2_env.pm_id)) continue;
- arr.push({
- pid : God.clusters_db[key].process.pid,
- name : God.clusters_db[key].pm2_env.name,
- pm2_env : God.clusters_db[key].pm2_env,
- pm_id : God.clusters_db[key].pm2_env.pm_id
- })
- }
- return arr;
- };
- /**
- * Description
- * @method findProcessById
- * @param {} id
- * @return ConditionalExpression
- */
- God.findProcessById = function findProcessById(id) {
- return God.clusters_db[id] ? God.clusters_db[id] : null;
- };
- /**
- * Description
- * @method findByName
- * @param {} name
- * @return arr
- */
- God.findByName = function(name) {
- var db = God.clusters_db;
- var arr = [];
- if (name == 'all') {
- for (var key in db) {
- // Avoid _old_proc process style
- if (typeof(God.clusters_db[key].pm2_env.pm_id) === 'number')
- arr.push(db[key]);
- }
- return arr;
- }
- for (var key in db) {
- if (God.clusters_db[key].pm2_env.name == name ||
- God.clusters_db[key].pm2_env.pm_exec_path == p.resolve(name)) {
- arr.push(db[key]);
- }
- }
- return arr;
- };
- /**
- * Check if a process is alive in system processes
- * Return TRUE if process online
- * @method checkProcess
- * @param {} pid
- * @return
- */
- God.checkProcess = function(pid) {
- if (!pid) return false;
- try {
- // Sending 0 signal do not kill the process
- process.kill(pid, 0);
- return true;
- }
- catch (err) {
- return false;
- }
- };
- /**
- * Description
- * @method processIsDead
- * @param {} pid
- * @param {} cb
- * @return Literal
- */
- God.processIsDead = function(pid, pm2_env, cb, sigkill) {
- if (!pid) return cb({type : 'param:missing', msg : 'no pid passed'});
- var timeout = null;
- var kill_timeout = (pm2_env && pm2_env.kill_timeout) ? pm2_env.kill_timeout : cst.KILL_TIMEOUT;
- var mode = pm2_env.exec_mode;
- var timer = setInterval(function() {
- if (God.checkProcess(pid) === false) {
- console.log('pid=%d msg=process killed', pid);
- clearTimeout(timeout);
- clearInterval(timer);
- return cb(null, true);
- }
- console.log('pid=%d msg=failed to kill - retrying in %dms', pid, pm2_env.kill_retry_time);
- return false;
- }, pm2_env.kill_retry_time);
- timeout = setTimeout(function() {
- clearInterval(timer);
- if (sigkill) {
- console.log('Process with pid %d could not be killed', pid);
- return cb({type : 'timeout', msg : 'timeout'});
- }
- else {
- console.log('Process with pid %d still alive after %sms, sending it SIGKILL now...', pid, kill_timeout);
- if (pm2_env.treekill !== true) {
- try {
- process.kill(parseInt(pid), 'SIGKILL');
- } catch(e) {
- console.error('[SimpleKill][SIGKILL] %s pid can not be killed', pid, e.stack, e.message);
- }
- return God.processIsDead(pid, pm2_env, cb, true);
- }
- else {
- treekill(parseInt(pid), 'SIGKILL', function(err) {
- return God.processIsDead(pid, pm2_env, cb, true);
- });
- }
- }
- }, kill_timeout);
- return false;
- };
- /**
- * Description
- * @method killProcess
- * @param int pid
- * @param Object pm2_env
- * @param function cb
- * @return CallExpression
- */
- God.killProcess = function(pid, pm2_env, cb) {
- if (!pid) return cb({msg : 'no pid passed or null'});
- if (typeof(pm2_env.pm_id) === 'number' &&
- (cst.KILL_USE_MESSAGE || pm2_env.shutdown_with_message == true)) {
- var proc = God.clusters_db[pm2_env.pm_id];
- if (proc && proc.send) {
- try {
- proc.send('shutdown');
- } catch (e) {
- console.error(`[AppKill] Cannot send "shutdown" message to ${pid}`)
- console.error(e.stack, e.message)
- }
- return God.processIsDead(pid, pm2_env, cb);
- }
- else {
- console.log(`[AppKill] ${pid} pid cannot be notified with send()`)
- }
- }
- if (pm2_env.treekill !== true) {
- try {
- process.kill(parseInt(pid), cst.KILL_SIGNAL);
- } catch(e) {
- console.error('[SimpleKill] %s pid can not be killed', pid, e.stack, e.message);
- }
- return God.processIsDead(pid, pm2_env, cb);
- }
- else {
- treekill(parseInt(pid), cst.KILL_SIGNAL, function(err) {
- return God.processIsDead(pid, pm2_env, cb);
- });
- }
- };
- /**
- * Description
- * @method getNewId
- * @return UpdateExpression
- */
- God.getNewId = function() {
- return God.next_id++;
- };
- /**
- * When a process is restarted or reloaded reset fields
- * to monitor unstable starts
- * @method resetState
- * @param {} pm2_env
- * @return
- */
- God.resetState = function(pm2_env) {
- pm2_env.created_at = Date.now();
- pm2_env.unstable_restarts = 0;
- pm2_env.prev_restart_delay = 0;
- };
- };
|