"v8": {
"type": [
"boolean"
]
},
"increment_var": {
"type": "string"
},
"instance_var": {

keep keep keep keep add keep keep keep keep

"event-loop-inspector": {
"type": [
"boolean"
]
},

/**
 * Copyright 2013 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.
 */
var shelljs       = require('shelljs');
var path          = require('path');
var fs            = require('fs');
var async         = require('async');
var p             = path;
var readline      = require('readline');
var spawn         = require('child_process').spawn;
var chalk         = require('chalk');
var Configuration = require('../../Configuration.js');
var cst           = require('../../../constants.js');
var Common        = require('../../Common');
var Utility       = require('../../Utility.js');
var ModularizerV1 = require('./Modularizerv1.js');
var Modularizer = module.exports = {};
var mkdirp = require('mkdirp');

var MODULE_CONF_PREFIX = 'module-db-v2';

/**
 * PM2 Module System.
 * Features:
 * - Installed modules are listed separately from user applications
 * - Always ON, a module is always up along PM2, to stop it, you need to uninstall it
 * - Install a runnable module from NPM/Github/HTTP (require a package.json only)
 * - Some modules add internal PM2 depencencies (like typescript, profiling...)
 * - Internally it uses NPM install (https://docs.npmjs.com/cli/install)
 * - Auto discover script to launch (first it checks the apps field, then bin and finally main attr)
 * - Generate sample module via pm2 module:generate <module_name>
 */
Modularizer.install = function(CLI, module_name, opts, cb) {
  Common.printOut(cst.PREFIX_MSG_MOD + 'Installing module ' + module_name);

  var canonic_module_name = Utility.getCanonicModuleName(module_name);

  if (module_name == 'v8-profiler' || module_name == 'profiler') {
    installLangModule('v8-profiler-node8', function(err) {
      if (err) {
        Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green('Profiling installation has FAILED (checkout previous logs)'));
        return cb(err);
      }

      Common.printOut(cst.PREFIX_MSG + chalk.bold.green('V8 profiling ENABLED'));
      return cb();
    });
    return false;
  }

  if (module_name === 'gc-stats') {
    installLangModule('gc-stats', function(err) {
      if (err) {
        Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green('gc-stats installation has FAILED (checkout previous logs)'));
        return cb(err);
      }

      Common.printOut(cst.PREFIX_MSG + chalk.bold.green('gc-stats ENABLED'));
      return cb();
    });
    return false;
  }

  if (module_name.indexOf('typescript') > -1) {
    // Special dependency install
    return installLangModule(module_name, function(e) {
      installLangModule('ts-node@latest', function(e) {
        Common.printOut(cst.PREFIX_MSG + chalk.bold.green('Typescript support enabled'));
        return cb(e);
      });
    });
  }

  if (module_name == 'livescript') {
    return installLangModule('livescript', function(e) {
      Common.printOut(cst.PREFIX_MSG + chalk.bold.green('Livescript support enabled'));
      return cb(e);
    });
  }

  if (module_name.indexOf('coffee-script') > -1) {
    return installLangModule(module_name, function(e) {
      Common.printOut(cst.PREFIX_MSG + chalk.bold.green('Coffeescript v1 support enabled'));
      return cb(e);
    });
  }

  if (module_name.indexOf('coffeescript') > -1) {
    return installLangModule(module_name, function(e) {
      Common.printOut(cst.PREFIX_MSG + chalk.bold.green('Coffeescript v2 support enabled'));
      return cb(e);
    });
  }

  moduleExist(CLI, canonic_module_name, function(exists) {
    if (exists) {
      // Update
      Common.printOut(cst.PREFIX_MSG_MOD + 'Module already installed. Updating.');

      // Create a backup
      Rollback.backup(module_name);

      return uninstallModule(CLI, {
        module_name : canonic_module_name,
        deep_uninstall : false
      }, function(err) {
        return Modularizer.installModule(CLI, module_name, opts, cb);
      });
    }

    // Install
    Modularizer.installModule(CLI, module_name, opts, cb);
  })
};

Modularizer.installModule = function(CLI, module_name, opts, cb) {
  var proc_path = '',
      cmd  = '',
      conf = {},
      development_mode = false;

  if (typeof(opts) == 'function') {
    cb = opts;
    opts = {};
  }

  if (module_name == '.') {
    /*******************
     * Development mode
     *******************/
    Common.printOut(cst.PREFIX_MSG_MOD + 'Installing local module in DEVELOPMENT MODE with WATCH auto restart');
    development_mode = true;
    proc_path = process.cwd();

    cmd = p.join(proc_path, cst.DEFAULT_MODULE_JSON);

    Common.extend(opts, {
      cmd : cmd,
      development_mode : development_mode,
      proc_path : proc_path
    });

    return startModule(CLI, opts, function(err, dt) {
      if (err) return cb(err);
      Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
      return cb(null, dt);
    });
  }

  /******************
   * Production mode
   ******************/
  Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');

  var canonic_module_name = Utility.getCanonicModuleName(module_name);
  var install_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);

  mkdirp(install_path, function() {
    process.chdir(process.env.HOME);

    var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error', '--prefix', install_path ], {
      stdio : 'inherit',
      env: process.env,
		  shell : true
    });

    install_instance.on('close', finalize);

    install_instance.on('error', function (err) {
      console.error(err.stack || err);
    });

  });

  function finalize(code) {
    if (code != 0) {
      // If install has failed, revert to previous module version
      return Rollback.revert(CLI, module_name, function() {
        return cb(new Error('Installation failed via NPM, module has been restored to prev version'));
      });
    }

    Common.printOut(cst.PREFIX_MSG_MOD + 'Module downloaded');

    var proc_path = path.join(install_path, 'node_modules', canonic_module_name);
    var package_json_path = path.join(proc_path, 'package.json');

    // Append default configuration to module configuration
    try {
      var conf = JSON.parse(fs.readFileSync(package_json_path).toString()).config;

      if (conf) {
        Object.keys(conf).forEach(function(key) {
          Configuration.setSyncIfNotExist(canonic_module_name + ':' + key, conf[key]);
        });
      }
    } catch(e) {
      Common.printError(e);
    }

    opts = Common.extend(opts, {
      cmd : package_json_path,
      development_mode : development_mode,
      proc_path : proc_path
    });

    Configuration.set(MODULE_CONF_PREFIX + ':' + canonic_module_name, {
      uid : opts.uid,
      gid : opts.gid
    }, function(err, data) {
      if (err) return cb(err);

      startModule(CLI, opts, function(err, dt) {
        if (err) return cb(err);

        if (process.env.PM2_PROGRAMMATIC === 'true')
          return cb(null, dt);

        CLI.conf(canonic_module_name, function() {
          Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
          Common.printOut(cst.PREFIX_MSG_MOD + 'Edit configuration via: `pm2 conf`');
          return cb(null, dt);
        });
      });
    });
  }
}

// Start V1 and V2 modules
Modularizer.launchAll = function(CLI, cb) {
  ModularizerV1.launchModules(CLI, function() {
    Modularizer.launchModules(CLI, cb);
  });
};

Modularizer.launchModules = function(CLI, cb) {
  var modules = Modularizer.listModules();

  if (!modules) return cb();

  async.eachLimit(Object.keys(modules), 1, function(module_name, next) {
    Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module_name);

    var install_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
    var proc_path = path.join(install_path, 'node_modules', module_name);
    var package_json_path = path.join(proc_path, 'package.json');

    var opts = {};

    // Merge with embedded configuration inside module_conf (uid, gid)
    Common.extend(opts, modules[module_name]);

    // Merge meta data to start module properly
    Common.extend(opts, {
      // package.json path
      cmd : package_json_path,
      // starting mode
      development_mode : false,
      // process cwd
      proc_path : proc_path
    });

    startModule(CLI, opts, function(err, dt) {
      if (err) console.error(err);
      return next();
    });

  }, function() {
    return cb ? cb(null) : false;
  });
}

function startModule(CLI, opts, cb) {
  if (!opts.cmd) throw new Error('module package.json not defined');
  if (!opts.development_mode) opts.development_mode = false;

  var package_json = require(opts.cmd);

  /**
   * Script file detection
   * 1- *apps* field (default pm2 json configuration)
   * 2- *bin* field
   * 3- *main* field
   */
  if (!package_json.apps) {
    package_json.apps = {};

    if (package_json.bin) {
      var bin = Object.keys(package_json.bin)[0];
      package_json.apps.script = package_json.bin[bin];
    }
    else if (package_json.main) {
      package_json.apps.script = package_json.main;
    }
  }

  Common.extend(opts, {
    cwd               : opts.proc_path,
    watch             : opts.development_mode,
    force_name        : package_json.name,
    started_as_module : true
  });

  // Start the module
  CLI.start(package_json, opts, function(err, data) {
    if (err) return cb(err);

    Common.printOut(cst.PREFIX_MSG_MOD + 'Monitoring module behavior for potential issue (5secs...)');

    if (opts.safe) {
      var time = typeof(opts.safe) == 'boolean' ? 3000 : parseInt(opts.safe);
      return setTimeout(function() {
        CLI.describe(package_json.name, function(err, apps) {
          if (err || apps[0].pm2_env.restart_time > 2) {
            return Rollback.revert(CLI, package_json.name, function() {
              return cb(new Error('New Module is instable, restored to previous version'));
            });
          }
          return cb(null, data);
        });
      }, time);
    }

    return cb(null, data);
  });
};

/**
 * Uninstall module
 */
Modularizer.uninstall = function(CLI, module_name, cb) {
  Common.printOut(cst.PREFIX_MSG_MOD + 'Uninstalling module ' + module_name);

  if (module_name == 'all') {
    var modules = Modularizer.listModules();

    if (!modules) return cb();

    return async.forEachLimit(Object.keys(modules), 1, function(module_name, next) {
      uninstallModule(CLI, {
        module_name : module_name,
        deep_uninstall : true
      }, next);
    }, cb);
  }

  var canonic_module_name = Utility.getCanonicModuleName(module_name);

  uninstallModule(CLI, {
    module_name : canonic_module_name,
    deep_uninstall : true
  }, cb);
};

function uninstallModule(CLI, opts, cb) {
  var module_name = opts.module_name;
  var proc_path = p.join(cst.PM2_ROOT_PATH, 'node_modules', module_name);

  try {
    // v1 uninstallation
    fs.statSync(proc_path)
    if (opts.deep_uninstall == true)
      Configuration.unsetSync('module-db:' + module_name);
  } catch(e) {
    proc_path = p.join(cst.DEFAULT_MODULE_PATH, module_name);
    if (opts.deep_uninstall == true)
      Configuration.unsetSync(MODULE_CONF_PREFIX + ':' + module_name);
  }

  CLI.deleteModule(module_name, function(err, data) {
    if (err) {
      Common.printError(err);

      if (module_name != '.') {
        console.log(proc_path);
        shelljs.rm('-r', proc_path);
      }

      return cb(err);
    }

    if (module_name != '.') {
      shelljs.rm('-r', proc_path);
    }

    return cb(null, data);
  });
}

var Rollback = {
  revert : function(CLI, module_name, cb) {
    var canonic_module_name = Utility.getCanonicModuleName(module_name);
    var backup_path = path.join(require('os').tmpdir(), canonic_module_name);
    var module_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);

    try {
      fs.statSync(backup_path)
    } catch(e) {
      return cb(new Error('no backup found'));
    }

    Common.printOut(cst.PREFIX_MSG_MOD + chalk.bold.red('[[[[[ Module installation failure! ]]]]]'));
    Common.printOut(cst.PREFIX_MSG_MOD + chalk.bold.red('[RESTORING TO PREVIOUS VERSION]'));

    CLI.deleteModule(canonic_module_name, function() {
      // Delete failing module
      shelljs.rm('-r', module_path);
      // Restore working version
      shelljs.cp('-r', backup_path, module_path);

      var proc_path = path.join(module_path, 'node_modules', canonic_module_name);
      var package_json_path = path.join(proc_path, 'package.json');

      // Start module
      startModule(CLI, {
        cmd : package_json_path,
        development_mode : false,
        proc_path : proc_path
      }, cb);
    });
  },
  backup : function(module_name) {
    // Backup current module
    var tmpdir = require('os').tmpdir();
    var canonic_module_name = Utility.getCanonicModuleName(module_name);
    var module_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);
    shelljs.cp('-r', module_path, tmpdir);
  }
}

/**
 * List modules based on modules present in ~/.pm2/modules/ folder
 */
Modularizer.listModules = function() {
  return Configuration.getSync(MODULE_CONF_PREFIX);
};

// Expose old module installation method for testing purpose
Modularizer.installModuleV1 = ModularizerV1.installModule;

Modularizer.getAdditionalConf = function(app_name) {
  if (!app_name) throw new Error('No app_name defined');

  var module_conf = Configuration.getAllSync();

  var additional_env = {};

  if (!module_conf[app_name]) {
    additional_env = {};
    additional_env[app_name] = {};
  }
  else {
    additional_env = Common.clone(module_conf[app_name]);
    additional_env[app_name] = JSON.stringify(module_conf[app_name]);
  }
  return additional_env;
};

/**
 * Publish a module
 */
Modularizer.publish = function(cb) {
  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });

  var semver = require('semver');

  var package_file = p.join(process.cwd(), 'package.json');

  var package_json = require(package_file);

  package_json.version = semver.inc(package_json.version, 'minor');
  Common.printOut(cst.PREFIX_MSG_MOD + 'Incrementing module to: %s@%s',
                  package_json.name,
                  package_json.version);

  rl.question("Write & Publish? [Y/N]", function(answer) {
    if (answer != "Y")
      return cb();

    fs.writeFile(package_file, JSON.stringify(package_json, null, 2), function(err, data) {
      if (err) return cb(err);

      Common.printOut(cst.PREFIX_MSG_MOD + 'Publishing module - %s@%s',
                      package_json.name,
                      package_json.version);

      shelljs.exec('npm publish', function(code) {
        Common.printOut(cst.PREFIX_MSG_MOD + 'Module - %s@%s successfully published',
                        package_json.name,
                        package_json.version);

        Common.printOut(cst.PREFIX_MSG_MOD + 'Pushing module on Git');
        shelljs.exec('git add . ; git commit -m "' + package_json.version + '"; git push origin master', function(code) {

          Common.printOut(cst.PREFIX_MSG_MOD + 'Installable with pm2 install %s', package_json.name);
          return cb(null, package_json);
        });
      });
    });

  });
};

Modularizer.generateSample = function(app_name, cb) {
  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });

  function samplize(module_name) {
    var cmd1 = 'git clone https://github.com/pm2-hive/sample-module.git ' + module_name + '; cd ' + module_name + '; rm -rf .git';
    var cmd2 = 'cd ' + module_name + ' ; sed -i "s:sample-module:'+ module_name  +':g" package.json';
    var cmd3 = 'cd ' + module_name + ' ; npm install';

    Common.printOut(cst.PREFIX_MSG_MOD + 'Getting sample app');
    shelljs.exec(cmd1, function(err) {
      if (err) Common.printError(cst.PREFIX_MSG_MOD_ERR + err.message);
      shelljs.exec(cmd2, function(err) {
        console.log('');
        shelljs.exec(cmd3, function(err) {
          console.log('');
          Common.printOut(cst.PREFIX_MSG_MOD + 'Module sample created in folder: ', path.join(process.cwd(), module_name));
          console.log('');
          Common.printOut('Start module in development mode:');
          Common.printOut('$ cd ' + module_name + '/');
          Common.printOut('$ pm2 install . ');
          console.log('');

          Common.printOut('Module Log: ');
          Common.printOut('$ pm2 logs ' + module_name);
          console.log('');
          Common.printOut('Uninstall module: ');
          Common.printOut('$ pm2 uninstall ' + module_name);
          console.log('');
          Common.printOut('Force restart: ');
          Common.printOut('$ pm2 restart ' + module_name);
          return cb ?  cb() : false;
        });
      });
    });
  }

  if (app_name) return samplize(app_name);

  rl.question(cst.PREFIX_MSG_MOD + "Module name: ", function(module_name) {
    samplize(module_name);
  });
};

function installLangModule(module_name, cb) {
  var node_module_path = path.resolve(path.join(__dirname, '../../../'));
  Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');

  var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error'], {
    stdio : 'inherit',
    env: process.env,
		shell : true,
    cwd : node_module_path
  });

  install_instance.on('close', function(code) {
    if (code > 0)
      return cb(new Error('Module install failed'));
    return cb(null);
  });

  install_instance.on('error', function (err) {
    console.error(err.stack || err);
  });
};

function moduleExist(CLI, module_name, cb) {
  // If old module, force his deletion
  var modules_v1 = Configuration.getSync('module-db');

  if (modules_v1) {
    modules_v1 = Object.keys(modules_v1);
    if (modules_v1.indexOf(module_name) > -1) {
      return uninstallModule(CLI, {
        module_name : module_name,
        deep_uninstall : true
      }, function() {
        cb(false);
      });
    }
  }

  var modules = Configuration.getSync(MODULE_CONF_PREFIX);
  if (!modules) return cb(false);
  modules = Object.keys(modules);
  return cb(modules.indexOf(module_name) > -1 ? true : false);
};


{
  "apps" : [{
    "exec_interpreter"   : "node,
    "exec_mode"          : "cluster_mode",
    "instances"          : 0,
    "log_date_format"    : "YYYY-MM-DD HH:mm Z",
    "max_memory_restart" : "160",
    "merge_logs"         : true,
    "name"               : "hapi_playground",
    "script"             : "child.js",
    "cwd"                : "examples",
    "node_args"          : "--harmony",
    "ignore_watch"        : ["[\\/\\\\]\\./", "log"],
    "watch"              : true
  }]
}


var axm = require('../..');

var probe = axm.probe();

var config_example = {
  val : 'hey',
  test : {
    a : 'good',
    sign : 'healthy'
  }
}

/**
 * Monitor value
 */

// This is ompossible to do :( (refresh value by pointer):
//
// probe.transpose('docker_config', config_example);

probe.transpose({
  name : 'style_2_docker_config',
  data : function doSomething() {
    return config_example;
  }
});

probe.transpose('style_1_docker_config', function doSomething() {
  return config_example;
});

setTimeout(function() {
  config_example.val = 'new value';
}, 1100);


#!/usr/bin/env bash

#export PM2_GRACEFUL_LISTEN_TIMEOUT=1000

SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/include.sh"
cd $file_path/listen-timeout/

echo -e "\033[1mENV REFRESH\033[0m"

$pm2 start wait-ready.js -i 1 --wait-ready --listen-timeout 5000

timeout 2 $pm2 reload all
should 'should have started 1 clustered app' 'online' 1
should 'should restart processes with new name' 'restart_time: 1' 1


*/
(function ProcessContainer() {
var fs          = require('fs');
if (process.env.pmx !== 'false')
require('pmx').init({

#!/usr/bin/env node
'use strict';

var semver = require('semver');

if (semver.satisfies(process.versions.node, '>= 5.7.0'))
  require('v8-compile-cache');

process.env.PM2_USAGE = 'CLI';

var cst       = require('../constants.js');

var commander = require('commander');
var chalk     = require('chalk');
var async     = require('async');

var debug     = require('debug')('pm2:cli');
var PM2       = require('../lib/API.js');
var pkg       = require('../package.json');
var tabtab    = require('../lib/completion.js');

// Early detection of silent to avoid printing motd
if (process.argv.indexOf('--silent') > -1 ||
    process.argv.indexOf('-s') > -1) {
  process.env.PM2_DISCRETE_MODE = true;
}

if (process.argv.indexOf('-v') > -1) {
  console.log(pkg.version);
  process.exit(0);
}

var pm2 = new PM2();

commander.version(pkg.version)
  .option('-v --version', 'get version')
  .option('-s --silent', 'hide all messages', false)
  .option('-m --mini-list', 'display a compacted list without formatting')
  .option('-f --force', 'force actions')
  .option('--disable-logs', 'do not write logs')
  .option('-n --name <name>', 'set a <name> for script')
  .option('-i --instances <number>', 'launch [number] instances (for networked app)(load balanced)')
  .option('--parallel <number>', 'number of parallel actions (for restart/reload)')
  .option('-l --log [path]', 'specify entire log file (error and out are both included)')
  .option('-o --output <path>', 'specify out log file')
  .option('-e --error <path>', 'specify error log file')
  .option('-p --pid <pid>', 'specify pid file')
  .option('-k --kill-timeout <delay>', 'delay before sending final SIGKILL signal to process')
  .option('--listen-timeout <delay>', 'listen timeout on application reload')
  .option('--max-memory-restart <memory>', 'specify max memory amount used to autorestart (in octet or use syntax like 100M)')
  .option('--restart-delay <delay>', 'specify a delay between restarts (in milliseconds)')
  .option('--env <environment_name>', 'specify environment to get specific env variables (for JSON declaration)')
  .option('--log-type <type>', 'specify log output style (raw by default, json optional)')
  .option('-x --execute-command', 'execute a program using fork system')
  .option('--max-restarts [count]', 'only restart the script COUNT times')
  .option('-u --user <username>', 'define user when generating startup script')
  .option('--uid <uid>', 'run target script with <uid> rights')
  .option('--gid <gid>', 'run target script with <gid> rights')
  .option('--cwd <path>', 'run target script as <username>')
  .option('--hp <home path>', 'define home path when generating startup script')
  .option('--wait-ip', 'override systemd script to wait for full internet connectivity to launch pm2')
  .option('--service-name <name>', 'define service name when generating startup script')
  .option('-c --cron <cron_pattern>', 'restart a running process based on a cron pattern')
  .option('-w --write', 'write configuration in local folder')
  .option('--interpreter <interpreter>', 'the interpreter pm2 should use for executing app (bash, python...)')
  .option('--interpreter-args <arguments>', 'interpret options (alias of --node-args)')
  .option('--log-date-format <date format>', 'add custom prefix timestamp to logs')
  .option('--no-daemon', 'run pm2 daemon in the foreground if it doesn\'t exist already')
  .option('-a --update-env', 'update environment on restart/reload (-a <=> apply)')
  .option('--source-map-support', 'force source map support')
  .option('--only <application-name>', 'with json declaration, allow to only act on one application')
  .option('--disable-source-map-support', 'force source map support')
  .option('--wait-ready', 'ask pm2 to wait for ready event from your app')
  .option('--merge-logs', 'merge logs from different instances but keep error and out separated')
  .option('--watch [paths]', 'watch application folder for changes', function(v, m) { m.push(v); return m;}, [])
  .option('--ignore-watch <folders|files>', 'folder/files to be ignored watching, should be a specific name or regex - e.g. --ignore-watch="test node_modules \"some scripts\""')
  .option('--node-args <node_args>', 'space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"')
  .option('--no-color', 'skip colors')
  .option('--no-vizion', 'start an app without vizion feature (versioning control)')
  .option('--no-autorestart', 'start an app without automatic restart')
  .option('--no-treekill', 'Only kill the main process, not detached children')
  .option('--no-pmx', 'start an app without pmx')
  .option('--no-automation', 'start an app without pmx')
  .option('--trace', 'enable transaction tracing with km')
  .option('--disable-trace', 'disable transaction tracing with km')
  .option('--attach', 'attach logging after your start/restart/stop/reload')
  .option('--sort <field_name:sort>', 'sort process according to field\'s name')
  .option('--v8', 'enable v8 data collecting')
  .usage('[cmd] app');

commander.on('--help', function() {
  console.log('  Basic Examples:');
  console.log('');
  console.log('    Start an app using all CPUs available + set a name :');
  console.log('    $ pm2 start app.js -i 0 --name "api"');
  console.log('');
  console.log('    Restart the previous app launched, by name :');
  console.log('    $ pm2 restart api');
  console.log('');
  console.log('    Stop the app :');
  console.log('    $ pm2 stop api');
  console.log('');
  console.log('    Restart the app that is stopped :');
  console.log('    $ pm2 restart api');
  console.log('');
  console.log('    Remove the app from the process list :');
  console.log('    $ pm2 delete api');
  console.log('');
  console.log('    Kill daemon pm2 :');
  console.log('    $ pm2 kill');
  console.log('');
  console.log('    Update pm2 :');
  console.log('    $ npm install pm2@latest -g ; pm2 update');
  console.log('');
  console.log('    More examples in https://github.com/Unitech/pm2#usagefeatures');
  console.log('');
  console.log('  Deployment help:');
  console.log('');
  console.log('    $ pm2 deploy help');
  console.log('');
  console.log('');
});

if (process.argv.indexOf('-s') > -1) {
  for(var key in console){
    var code = key.charCodeAt(0);
    if(code >= 97 && code <= 122){
      console[key] = function(){};
    }
  }
}

function beginCommandProcessing() {
  pm2.getVersion(function(err, remote_version) {
    if (!err && (pkg.version != remote_version)) {
      console.log('');
      console.log(chalk.red.bold('>>>> In-memory PM2 is out-of-date, do:\n>>>> $ pm2 update'));
      console.log('In memory PM2 version:', chalk.blue.bold(remote_version));
      console.log('Local PM2 version:', chalk.blue.bold(pkg.version));
      console.log('');
    }
  });
  commander.parse(process.argv);
}

function checkCompletion(){
  return tabtab.complete('pm2', function(err, data) {
    if(err || !data) return;
    if(/^--\w?/.test(data.last)) return tabtab.log(commander.options.map(function (data) {
      return data.long;
    }), data);
    if(/^-\w?/.test(data.last)) return tabtab.log(commander.options.map(function (data) {
      return data.short;
    }), data);
    // array containing commands after which process name should be listed
    var cmdProcess = ['stop', 'restart', 'scale', 'reload', 'gracefulReload', 'delete', 'reset', 'pull', 'forward', 'backward', 'logs', 'describe', 'desc', 'show'];

    if (cmdProcess.indexOf(data.prev) > -1) {
      pm2.list(function(err, list){
        tabtab.log(list.map(function(el){ return el.name }), data);
        pm2.disconnect();
      });
    }
    else if (data.prev == 'pm2') {
      tabtab.log(commander.commands.map(function (data) {
        return data._name;
      }), data);
      pm2.disconnect();
    }
    else
      pm2.disconnect();
  });
};

var _arr = process.argv.indexOf('--') > -1 ? process.argv.slice(0, process.argv.indexOf('--')) : process.argv;

if (_arr.indexOf('log') > -1) {
  process.argv[_arr.indexOf('log')] = 'logs';
}

if (_arr.indexOf('--no-daemon') > -1) {
  //
  // Start daemon if it does not exist
  //
  // Function checks if --no-daemon option is present,
  // and starts daemon in the same process if it does not exists
  //
  console.log('pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)');

  var pm2NoDaeamon = new PM2({
    daemon_mode : false
  });

  pm2NoDaeamon.connect(function() {
    pm2 = pm2NoDaeamon;
    beginCommandProcessing();
  });

}
else if (_arr.indexOf('startup') > -1 || _arr.indexOf('unstartup') > -1) {
  setTimeout(function() {
    commander.parse(process.argv);
  }, 100);
}
else {
  // HERE we instanciate the Client object
  pm2.connect(function() {
    debug('Now connected to daemon');
    if (process.argv.slice(2)[0] === 'completion') {
      checkCompletion();
      //Close client if completion related installation
      var third = process.argv.slice(3)[0];
      if ( third == null || third === 'install' || third === 'uninstall')
        pm2.disconnect();
    }
    else {
      beginCommandProcessing();
    }
  });
}

//
// Helper function to fail when unknown command arguments are passed
//
function failOnUnknown(fn) {
  return function(arg) {
    if (arguments.length > 1) {
      console.log(cst.PREFIX_MSG + '\nUnknown command argument: ' + arg);
      commander.outputHelp();
      process.exit(cst.ERROR_EXIT);
    }
    return fn.apply(this, arguments);
  };
}

/**
 * @todo to remove at some point once it's fixed in official commander.js
 * https://github.com/tj/commander.js/issues/475
 *
 * Patch Commander.js Variadic feature
 */
function patchCommanderArg(cmd) {
  var argsIndex;
  if ((argsIndex = commander.rawArgs.indexOf('--')) >= 0) {
    var optargs = commander.rawArgs.slice(argsIndex + 1);
    cmd = cmd.slice(0, cmd.indexOf(optargs[0]));
  }
  return cmd;
}

//
// Start command
//
commander.command('start <file|json|stdin|app_name|pm_id...>')
  .option('--watch', 'Watch folder for changes')
  .option('--fresh', 'Rebuild Dockerfile')
  .option('--daemon', 'Run container in Daemon mode (debug purposes)')
  .option('--container', 'Start application in container mode')
  .option('--dist', 'with --container; change local Dockerfile to containerize all files in current directory')
  .option('--image-name [name]', 'with --dist; set the exported image name')
  .option('--node-version [major]', 'with --container, set a specific major Node.js version')
  .option('--dockerdaemon', 'for debugging purpose')
  .description('start and daemonize an app')
  .action(function(cmd, opts) {
    if (opts.container == true && opts.dist == true)
      return pm2.dockerMode(cmd, opts, 'distribution');
    else if (opts.container == true)
      return pm2.dockerMode(cmd, opts, 'development');

    if (cmd == "-") {
      process.stdin.resume();
      process.stdin.setEncoding('utf8');
      process.stdin.on('data', function (cmd) {
        process.stdin.pause();
        pm2._startJson(cmd, commander, 'restartProcessId', 'pipe');
      });
    }
    else {
      // Commander.js patch
      cmd = patchCommanderArg(cmd);
      async.forEachLimit(cmd, 1, function(script, next) {
        pm2.start(script, commander, next);
      }, function(err) {
        pm2.speedList(err ? 1 : 0);
      });
    }
  });

commander.command('trigger <proc_name> <action_name> [params]')
  .description('deploy your json')
  .action(function(pm_id, action_name, params) {
    pm2.trigger(pm_id, action_name, params);
  });

commander.command('deploy <file|environment>')
  .description('deploy your json')
  .action(function(cmd) {
    pm2.deploy(cmd, commander);
  });

commander.command('startOrRestart <json>')
  .description('start or restart JSON file')
  .action(function(file) {
    pm2._startJson(file, commander, 'restartProcessId');
  });

commander.command('startOrReload <json>')
  .description('start or gracefully reload JSON file')
  .action(function(file) {
    pm2._startJson(file, commander, 'reloadProcessId');
  });

commander.command('startOrGracefulReload <json>')
  .description('start or gracefully reload JSON file')
  .action(function(file) {
    pm2._startJson(file, commander, 'softReloadProcessId');
  });

//
// Stop specific id
//
commander.command('stop <id|name|all|json|stdin...>')
  .option('--watch', 'Stop watching folder for changes')
  .description('stop a process (to start it again, do pm2 restart <app>)')
  .action(function(param) {
    async.forEachLimit(param, 1, function(script, next) {
      pm2.stop(script, next);
    }, function(err) {
      pm2.speedList(err ? 1 : 0);
    });
  });

//
// Stop All processes
//
commander.command('restart <id|name|all|json|stdin...>')
  .option('--watch', 'Toggle watching folder for changes')
  .description('restart a process')
  .action(function(param) {
    // Commander.js patch
    param = patchCommanderArg(param);
    async.forEachLimit(param, 1, function(script, next) {
      pm2.restart(script, commander, next);
    }, function(err) {
      pm2.speedList(err ? 1 : 0);
    });
  });

//
// Scale up/down a process in cluster mode
//
commander.command('scale <app_name> <number>')
  .description('scale up/down a process in cluster mode depending on total_number param')
  .action(function(app_name, number) {
    pm2.scale(app_name, number);
  });

//
// snapshot PM2
//
commander.command('snapshot')
  .description('snapshot PM2 memory')
  .action(function() {
    pm2.snapshotPM2();
  });

//
// snapshot PM2
//
commander.command('profile <command>')
  .description('profile CPU')
  .action(function(command) {
    pm2.profilePM2(command);
  });

//
// Reload process(es)
//
commander.command('reload <name|all>')
  .description('reload processes (note that its for app using HTTP/HTTPS)')
  .action(function(pm2_id) {
    pm2.reload(pm2_id, commander);
  });

//
// Reload process(es)
//
commander.command('gracefulReload <name|all>')
  .description('gracefully reload a process. Send a "shutdown" message to close all connections.')
  .action(function(pm2_id) {
    pm2.gracefulReload(pm2_id, commander);
  });

commander.command('id <name>')
  .description('get process id by name')
  .action(function(name) {
    pm2.getProcessIdByName(name);
  });

//
// Stop and delete a process by name from database
//
commander.command('delete <name|id|script|all|json|stdin...>')
  .description('stop and delete a process from pm2 process list')
  .action(function(name) {
    if (name == "-") {
      process.stdin.resume();
      process.stdin.setEncoding('utf8');
      process.stdin.on('data', function (param) {
        process.stdin.pause();
        pm2.delete(param, 'pipe');
      });
    } else
      async.forEachLimit(name, 1, function(script, next) {
        pm2.delete(script,'', next);
      }, function(err) {
        pm2.speedList(err ? 1 : 0);
      });
  });

//
// Send system signal to process
//
commander.command('sendSignal <signal> <pm2_id|name>')
  .description('send a system signal to the target process')
  .action(function(signal, pm2_id) {
    if (isNaN(parseInt(pm2_id))) {
      console.log(cst.PREFIX_MSG + 'Sending signal to process name ' + pm2_id);
      pm2.sendSignalToProcessName(signal, pm2_id);
    } else {
      console.log(cst.PREFIX_MSG + 'Sending signal to process id ' + pm2_id);
      pm2.sendSignalToProcessId(signal, pm2_id);
    }
  });

//
// Stop and delete a process by name from database
//
commander.command('ping')
  .description('ping pm2 daemon - if not up it will launch it')
  .action(function() {
    pm2.ping();
  });

commander.command('updatePM2')
  .description('update in-memory PM2 with local PM2')
  .action(function() {
    pm2.update();
  });
commander.command('update')
  .description('(alias) update in-memory PM2 with local PM2')
  .action(function() {
    pm2.update();
  });

/**
 * Module specifics
 */
commander.command('install <module|git:// url>')
  .alias('module:install')
  .option('--v1', 'install module in v1 manner (do not use it)')
  .option('--safe [time]', 'keep module backup, if new module fail = restore with previous')
  .description('install or update a module and run it forever')
  .action(function(plugin_name, opts) {
    if (opts.v1)
      commander.v1 = true;
    if (opts.safe)
      commander.safe = opts.safe;
    pm2.install(plugin_name, commander);
  });

commander.command('module:update <module|git:// url>')
  .description('update a module and run it forever')
  .action(function(plugin_name) {
    pm2.install(plugin_name);
  });

commander.command('module:generate [app_name]')
  .description('Generate a sample module in current folder')
  .action(function(app_name) {
    pm2.generateModuleSample(app_name);
  });

commander.command('uninstall <module>')
  .alias('module:uninstall')
  .description('stop and uninstall a module')
  .action(function(plugin_name) {
    pm2.uninstall(plugin_name);
  });

commander.command('publish')
  .alias('module:publish')
  .description('Publish the module you are currently on')
  .action(function() {
    pm2.publish();
  });

commander.command('set [key] [value]')
  .description('sets the specified config <key> <value>')
  .action(function(key, value) {
    pm2.set(key, value);
  });

commander.command('multiset <value>')
  .description('multiset eg "key1 val1 key2 val2')
  .action(function(str) {
    pm2.multiset(str);
  });

commander.command('get [key]')
  .description('get value for <key>')
  .action(function(key) {
    pm2.get(key);
  });

commander.command('conf [key] [value]')
  .description('get / set module config values')
  .action(function(key, value) {
    pm2.conf(key, value);
  });

commander.command('config <key> [value]')
  .description('get / set module config values')
  .action(function(key, value) {
    pm2.conf(key, value);
  });

commander.command('unset <key>')
  .description('clears the specified config <key>')
  .action(function(key) {
    pm2.unset(key);
  });

commander.command('report')
  .description('give a full pm2 report for https://github.com/Unitech/pm2/issues')
  .action(function(key) {
    pm2.report();
  });

//
// Keymetrics CLI integratio
//
commander.command('link [secret] [public] [name]')
  .alias('interact')
  .option('--info-node [url]', 'set url info node')
  .description('linking action to keymetrics.io - command can be stop|info|delete|restart')
  .action(pm2._pre_interact.bind(pm2));

commander.command('unlink')
  .description('linking action to keymetrics.io - command can be stop|info|delete|restart')
  .action(function() {
    pm2.unlink();
  });

commander.command('unmonitor [name]')
  .description('unmonitor target process')
  .action(function(name) {
    pm2.monitorState('unmonitor', name);
  });

commander.command('monitor [name]')
  .description('monitor target process')
  .action(function(name) {
    pm2.monitorState('monitor', name);
  });

commander.command('open')
  .description('open dashboard in browser')
  .action(function(name) {
    pm2.openDashboard();
  });

commander.command('register')
  .description('create an account on keymetrics')
  .action(function(name) {
    pm2.registerToKM();
  });

commander.command('login')
  .description('login to keymetrics and link current PM2')
  .action(function(name) {
    pm2.loginToKM();
  });

//
// Web interface
//
commander.command('web')
  .description('launch a health API on ' + cst.WEB_IPADDR + ':' + cst.WEB_PORT)
  .action(function() {
    console.log('Launching web interface on ' + cst.WEB_IPADDR + ':' + cst.WEB_PORT);
    pm2.web();
  });

//
// Save processes to file
//
commander.command('dump')
  .alias('save')
  .description('dump all processes for resurrecting them later')
  .action(failOnUnknown(function() {
    pm2.dump();
  }));

//
// Save processes to file
//
commander.command('send <pm_id> <line>')
  .description('send stdin to <pm_id>')
  .action(function(pm_id, line) {
    pm2.sendLineToStdin(pm_id, line);
  });

//
// Attach to stdin/stdout
// Not TTY ready
//
commander.command('attach <pm_id> [command separator]')
  .description('attach stdin/stdout to application identified by <pm_id>')
  .action(function(pm_id, separator) {
    pm2.attach(pm_id, separator);
  });

//
// Resurrect
//
commander.command('resurrect')
  .description('resurrect previously dumped processes')
  .action(failOnUnknown(function() {
    console.log(cst.PREFIX_MSG + 'Resurrecting');
    pm2.resurrect();
  }));

//
// Set pm2 to startup
//
commander.command('unstartup [platform]')
  .description('disable and clear auto startup - [platform]=systemd,upstart,launchd,rcd')
  .action(function(platform) {
    pm2.uninstallStartup(platform, commander);
  });

//
// Set pm2 to startup
//
commander.command('startup [platform]')
  .description('setup script for pm2 at boot - [platform]=systemd,upstart,launchd,rcd')
  .action(function(platform) {
    pm2.startup(platform, commander);
  });

//
// Logrotate
//
commander.command('logrotate')
  .description('copy default logrotate configuration')
  .action(function(cmd) {
    pm2.logrotate(commander);
  });

//
// Sample generate
//

commander.command('ecosystem [mode]')
  .alias('generate')
  .description('generate a process conf file. (mode = null or simple)')
  .action(function(mode) {
    pm2.generateSample(mode);
  });

commander.command('reset <name|id|all>')
  .description('reset counters for process')
  .action(function(proc_id) {
    pm2.reset(proc_id);
  });

commander.command('describe <id>')
  .description('describe all parameters of a process id')
  .action(function(proc_id) {
    pm2.describe(proc_id);
  });

commander.command('desc <id>')
  .description('(alias) describe all parameters of a process id')
  .action(function(proc_id) {
    pm2.describe(proc_id);
  });

commander.command('info <id>')
  .description('(alias) describe all parameters of a process id')
  .action(function(proc_id) {
    pm2.describe(proc_id);
  });

commander.command('show <id>')
  .description('(alias) describe all parameters of a process id')
  .action(function(proc_id) {
    pm2.describe(proc_id);
  });

//
// List command
//
commander
  .command('list')
  .alias('ls')
  .description('list all processes')
  .action(function() {
    pm2.list(commander)
  });

commander.command('l')
  .description('(alias) list all processes')
  .action(function() {
    pm2.list()
  });

commander.command('ps')
  .description('(alias) list all processes')
  .action(function() {
    pm2.list()
  });

commander.command('status')
  .description('(alias) list all processes')
  .action(function() {
    pm2.list()
  });

// List in raw json
commander.command('jlist')
  .description('list all processes in JSON format')
  .action(function() {
    pm2.jlist()
  });

// List in prettified Json
commander.command('prettylist')
  .description('print json in a prettified JSON')
  .action(failOnUnknown(function() {
    pm2.jlist(true);
  }));

//
// Dashboard command
//
commander.command('monit')
  .description('launch termcaps monitoring')
  .action(function() {
    pm2.dashboard();
  });

commander.command('imonit')
  .description('launch legacy termcaps monitoring')
  .action(function() {
    pm2.monit();
  });

commander.command('dashboard')
  .alias('dash')
  .description('launch dashboard with monitoring and logs')
  .action(function() {
    pm2.dashboard();
  });

//
// Flushing command
//
commander.command('flush')
  .description('flush logs')
  .action(failOnUnknown(function() {
    pm2.flush();
  }));

//
// Reload all logs
//
commander.command('reloadLogs')
  .description('reload all logs')
  .action(function() {
    pm2.reloadLogs();
  });

//
// Log streaming
//
commander.command('logs [id|name]')
  .option('--json', 'json log output')
  .option('--format', 'formated log output')
  .option('--raw', 'raw output')
  .option('--err', 'only shows error output')
  .option('--out', 'only shows standard output')
  .option('--lines <n>', 'output the last N lines, instead of the last 15 by default')
  .option('--timestamp [format]', 'add timestamps (default format YYYY-MM-DD-HH:mm:ss)')
  .option('--nostream', 'print logs without lauching the log stream')
  .description('stream logs file. Default stream all logs')
  .action(function(id, cmd) {
    var Logs = require('../lib/API/Log.js');

    if (!id) id = 'all';

    var line = 15;
    var raw  = false;
    var exclusive = false;
    var timestamp = false;

    if(!isNaN(parseInt(cmd.lines))) {
      line = parseInt(cmd.lines);
    }

    if (cmd.parent.rawArgs.indexOf('--raw') !== -1)
      raw = true;

    if (cmd.timestamp)
      timestamp = typeof cmd.timestamp === 'string' ? cmd.timestamp : 'YYYY-MM-DD-HH:mm:ss';

    if (cmd.out === true)
      exclusive = 'out';

    if (cmd.err === true)
      exclusive = 'err';

    if (cmd.nostream === true)
      pm2.printLogs(id, line, raw, timestamp, exclusive);
    else if (cmd.json === true)
      Logs.jsonStream(pm2.Client, id);
    else if (cmd.format === true)
      Logs.formatStream(pm2.Client, id, false, 'YYYY-MM-DD-HH:mm:ssZZ');
    else
      pm2.streamLogs(id, line, raw, timestamp, exclusive);
  });

//
// Kill
//
commander.command('kill')
  .description('kill daemon')
  .action(failOnUnknown(function(arg) {
    pm2.killDaemon(function() {
      process.exit(cst.SUCCESS_EXIT);
    });
  }));

//
// Update repository for a given app
//

commander.command('pull <name> [commit_id]')
  .description('updates repository for a given app')
  .action(function(pm2_name, commit_id) {

    if (commit_id !== undefined) {
      pm2._pullCommitId({
        pm2_name: pm2_name,
        commit_id: commit_id
      });
    }
    else
      pm2.pullAndRestart(pm2_name);
  });

//
// Update repository to the next commit for a given app
//
commander.command('forward <name>')
  .description('updates repository to the next commit for a given app')
  .action(function(pm2_name) {
    pm2.forward(pm2_name);
  });

//
// Downgrade repository to the previous commit for a given app
//
commander.command('backward <name>')
  .description('downgrades repository to the previous commit for a given app')
  .action(function(pm2_name) {
    pm2.backward(pm2_name);
  });

//
// Force PM2 to trigger garbage collection
//
commander.command('gc')
  .description('force PM2 to trigger garbage collection')
  .action(function() {
    pm2.forceGc();
  });

//
// Perform a deep update of PM2
//
commander.command('deepUpdate')
  .description('performs a deep update of PM2')
  .action(function() {
    pm2.deepUpdate();
  });

//
// Launch a http server that expose a given path on given port
//
commander.command('serve [path] [port]')
  .alias('expose')
  .description('serve a directory over http via port')
  .action(function (path, port) {
    pm2.serve(path, port, commander);
  });

//
// Catch all
//
commander.command('*')
  .action(function() {
    console.log(cst.PREFIX_MSG + '\nCommand not found');
    commander.outputHelp();
    // Check if it does not forget to close fds from RPC
    process.exit(cst.ERROR_EXIT);
  });

//
// Display help if 0 arguments passed to pm2
//
if (process.argv.length == 2) {
  commander.parse(process.argv);
  commander.outputHelp();
  // Check if it does not forget to close fds from RPC
  process.exit(cst.ERROR_EXIT);
}


Unnamed repository; edit this file 'description' to name the repository.


var axm = require('../..');

var obj = axm.enableProbes();

var i = 2;

obj.it_works = true;
obj.value = 20;
obj.i = i;

setTimeout(function() {
  i = 4;
  obj.it_works = false;
  obj.value = 99;

  setTimeout(function() {
    axm.stopProbes();
  }, 1100);
}, 1100);


transactions: (process.env.km_link === 'true' && process.env.trace === 'true') || false,

http: process.env.km_link === 'true' || false,

event_loop_dump: process.env['event-loop-inspector'] === 'true' || false

/**
 * Copyright 2013 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.
 *
 * This file wrap target application
 * - redirect stdin, stderr to bus + log files
 * - rename process
 * - pid
 */

var p       = require('path');
var cst     = require('../constants');
var Utility = require('./Utility.js');

// Load all env-vars from master.
var pm2_env = JSON.parse(process.env.pm2_env);
for(var k in pm2_env) {
  process.env[k] = pm2_env[k];
}

// Rename process
process.title = process.env.PROCESS_TITLE || 'node ' + pm2_env.pm_exec_path;

delete process.env.pm2_env;

/**
 * Main entrance to wrap the desired code
 */
(function ProcessContainer() {
  var fs          = require('fs');

  if (process.env.pmx !== 'false')
    require('pmx').init({
      transactions: process.env.km_link == 'true' && process.env.trace == 'true' || false,
      http: process.env.km_link == 'true' || false,
      v8: process.env.v8 === 'true' || false
    });

  var stdFile     = pm2_env.pm_log_path;
  var outFile     = pm2_env.pm_out_log_path;
  var errFile     = pm2_env.pm_err_log_path;
  var pmId        = pm2_env.pm_id;
  var pidFile     = pm2_env.pm_pid_path;
  var script      = pm2_env.pm_exec_path;
  var cronRestart = pm2_env.cron_restart;

  var original_send = process.send;

  if (typeof(process.env.source_map_support) != 'undefined' &&
      process.env.source_map_support !== 'false') {
    require('source-map-support').install();
  }

  process.send = function() {
    if (process.connected)
      original_send.apply(this, arguments);
  };

  //send node version
  if (process.versions && process.versions.node) {
    process.send({
      'node_version': process.versions.node
    });
  }

  if (cst.MODIFY_REQUIRE)
    require.main.filename = pm2_env.pm_exec_path;

  // Resets global paths for require()
  require('module')._initPaths();

  try {
    fs.writeFileSync(pidFile, process.pid);
  } catch (e) {
    console.error(e.stack || e);
  }

  // Add args to process if args specified on start
  if (process.env.args != null)
    process.argv = process.argv.concat(pm2_env.args);

  // stdio, including: out, err and entire (both out and err if necessary).
  var stds = {
    out: outFile,
    err: errFile
  };
  stdFile && (stds.std = stdFile);

  // uid/gid management
  if (pm2_env.uid || pm2_env.gid) {
    try {
      if (pm2_env.uid)
        process.setuid(pm2_env.uid);
      if (process.env.gid)
        process.setgid(pm2_env.gid);
    } catch(e) {
      setTimeout(function() {
        console.error('%s on call %s', e.message, e.syscall);
        console.error('%s is not accessible', pm2_env.uid);
        return process.exit(1);
      }, 100);
    }
  }

  exec(script, stds);

  if (cronRestart)
    cronize(cronRestart);
})();

/**
 * Cron restart
 */
function cronize(cron_pattern) {
  var cronJob = require('cron').CronJob;
  var job = new cronJob({
    cronTime: cron_pattern,
    onTick  : function() {
      if (process.connected && process.send) {
        process.send({
          'cron_restart': 1
        });
      } else {
        process.emit('disconnect');
        process.nextTick(function() {
          process.exit(0);
        });
      }
    },
    start: false
  });
  job.start();
}

/**
 * Description
 * @method exec
 * @param {} script
 * @param {} stds
 * @return
 */
function exec(script, stds) {
  if (p.extname(script) == '.coffee') {
    try {
      require('coffee-script/register');
    } catch (e) {
      console.error('Failed to load CoffeeScript interpreter:', e.message || e);
    }
  }

  if (p.extname(script) == '.ls') {
    try {
      require('livescript');
    } catch (e) {
      console.error('Failed to load LiveScript interpreter:', e.message || e);
    }
  }

  if (p.extname(script) == '.ts' || p.extname(script) == '.tsx') {
    try {
      require('ts-node/register');
    } catch (e) {
      console.error('Failed to load Typescript interpreter:', e.message || e);
    }
  }

  process.on('message', function (msg) {
    if (msg.type === 'log:reload') {
      for (var k in stds){
        if (typeof stds[k] == 'object' && !isNaN(stds[k].fd)){
          if (stds[k].destroy) stds[k].destroy();
          else if (stds[k].end) stds[k].end();
          else if (stds[k].close) stds[k].close();
          stds[k] = stds[k]._file;
        }
      }
      Utility.startLogging(stds, function (err) {
        if (err)
          return console.error('Failed to reload logs:', err.stack);
        console.log('Reloading log...');
      });
    }
  });

  var moment = null;

  if (pm2_env.log_date_format)
    moment = require('moment');

  Utility.startLogging(stds, function (err) {
    if (err) {
      process.send({
        type    : 'process:exception',
        data    : {
          message: err.message,
          syscall: 'ProcessContainer.startLogging'
        }
      });
      throw err;
      return;
    }

    process.stderr.write = (function(write) {
      return function(string, encoding, cb) {
        var log_data = null;

        // Disable logs if specified
        if (pm2_env.disable_logs === true) {
          return cb ? cb() : false;
        }

        if (pm2_env.log_type && pm2_env.log_type === 'json') {
          log_data = JSON.stringify({
            message : string.toString(),
            timestamp : pm2_env.log_date_format && moment ?
              moment().format(pm2_env.log_date_format) : new Date().toISOString(),
            type : 'err',
            process_id : pm2_env.pm_id,
            app_name : pm2_env.name
          }) + '\n';
        }
        else if (pm2_env.log_date_format && moment)
          log_data = moment().format(pm2_env.log_date_format) + ': ' + string.toString();
        else
          log_data = string.toString();

        process.send({
          type : 'log:err',
          data : log_data
        });

        if (Utility.checkPathIsNull(pm2_env.pm_err_log_path) &&
          (!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
          return cb ? cb() : false;

        stds.std && stds.std.write && stds.std.write(log_data, encoding);
        stds.err && stds.err.write && stds.err.write(log_data, encoding, cb);
      };
    })(process.stderr.write);

    process.stdout.write = (function(write) {
      return function(string, encoding, cb) {
        var log_data = null;

        // Disable logs if specified
        if (pm2_env.disable_logs === true) {
          return cb ? cb() : false;
        }

        if (pm2_env.log_type && pm2_env.log_type === 'json') {
          log_data = JSON.stringify({
            message : string.toString(),
            timestamp : pm2_env.log_date_format && moment ?
              moment().format(pm2_env.log_date_format) : new Date().toISOString(),
            type : 'out',
            process_id : pm2_env.pm_id,
            app_name : pm2_env.name
          }) + '\n';
        }
        else if (pm2_env.log_date_format && moment)
          log_data = moment().format(pm2_env.log_date_format) + ': ' + string.toString();
        else
          log_data = string.toString();

        process.send({
          type : 'log:out',
          data : log_data
        });

        if (Utility.checkPathIsNull(pm2_env.pm_out_log_path) &&
          (!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
          return cb ? cb() : null;

        stds.std && stds.std.write && stds.std.write(log_data, encoding);
        stds.out && stds.out.write && stds.out.write(log_data, encoding, cb);
      };
    })(process.stdout.write);

    function getUncaughtExceptionListener(listener) {
      return function uncaughtListener(err) {
        var error = err && err.stack ? err.stack : err;

        if (listener === 'unhandledRejection') {
          error = 'You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:\n' + error;
        }

        logError(['std', 'err'], error);

        // Notify master that an uncaughtException has been catched
        try {
          if (err) {
            var errObj = {};

            Object.getOwnPropertyNames(err).forEach(function(key) {
              errObj[key] = err[key];
            });
          }

          process.send({
            type : 'log:err',
            data : '\n' + error + '\n'
          });
          process.send({
            type    : 'process:exception',
            data    : errObj !== undefined ? errObj : {message: 'No error but ' + listener + ' was caught!'}
          });
        } catch(e) {
          logError(['std', 'err'], 'Channel is already closed can\'t broadcast error:\n' + e.stack);
        }

        if (!process.listeners(listener).filter(function (listener) {
            return listener !== uncaughtListener;
        }).length) {
          if (listener == 'uncaughtException') {
            process.emit('disconnect');
            process.exit(cst.CODE_UNCAUGHTEXCEPTION);
          }
        }
      }
    }

    process.on('uncaughtException', getUncaughtExceptionListener('uncaughtException'));
    process.on('unhandledRejection', getUncaughtExceptionListener('unhandledRejection'));

    // Change dir to fix process.cwd
    process.chdir(pm2_env.pm_cwd || process.env.PWD || p.dirname(script));

    require('module')._load(script, null, true);

    function logError(types, error){
      try {
        types.forEach(function(type){
          stds[type] && typeof stds[type].write == 'function' && stds[type].write(error + '\n');
        });
      } catch(e) { }
    }
  });

}


# PM2 production process manager

## Table of contents

### Quick start

- [Installation](#a1)
- [How to update PM2?](#update-pm2)
- [PM2 tab-completion](#tab-completion)
- [Allow PM2 to bind apps on port 80/443 without root](#authbind-pm2)

### Features

- [Transitional state of apps](#a4)
- [Process listing](#a6)
- [Automatic restart process based on memory](#max-memory-restart)
- [Monitoring CPU/Memory usage](#a7)
- [Logs management](#a9)
- [Clustering](#a5)
- [Multiple PM2 on the same server](#multiple-pm2)
- [Watch & Restart](#watch--restart)
- [Reloading without downtime](#hot-reload--0s-reload)
- [Make PM2 restart on server reboot](#a8)
- [JS/JSON app declaration](#jsjson-app-declaration)
  - [Options list](#list-of-all-json-declaration-fields-avaibles)
  - [Schema](#schema)
- [Using PM2 in development](#using-pm2-in-development)
- [Use ES6](#run-next-generation-javascript)

### [Using PM2 in Cloud Providers (Heroku/Google App Engine/Azure)](https://github.com/Unitech/PM2/blob/development/ADVANCED_README.md#using-pm2-in-cloud-providers-1)

- [Without Keymetrics](#without-keymetrics)
- [With Keymetrics](#with-keymetrics)

### Deployment - ecosystem.json

- [Getting started with deployment](#deployment)
- [Deployment options](#deployment-help)
- [Considerations](#considerations)
- [Contributing](#deployment-contribution)

### Using PM2 programmatically (via API)

- [Simple example](#programmatic-example)
- [Programmatic API](#programmatic-api)

### Specific

- [Specific features](#a77)
- [Configuration file](#a989)
- [Enabling Harmony ES6](#a66)
- [CoffeeScript](#a19)
- [Testing PM2 on your prod environment](#a149)
- [JSON app via pipe](#a96)

### Knowledge

- [Stateless apps ?](#stateless-apps)
- [Transitional state of apps](#a4)
- [Setup PM2 on server: tutorial](#a89)
- [Logs and PID files](#a34)
- [Execute any script: What is fork mode ?](#a23)

### More

- [Contributing/Development mode](#a27)
- [Known bugs and workaround](#a21)
- [They talk about it](#a20)
- [License](#a15)

------

# Quick start

## Installation

[Quick Start](http://pm2.keymetrics.io/docs/usage/quick-start/)

## How to update PM2

[Update PM2](http://pm2.keymetrics.io/docs/usage/quick-start/#how-to-update-pm2)

## PM2 tab-completion

[Tab-completion for pm2](http://pm2.keymetrics.io/docs/usage/auto-completion/)

# Features

## Managing applications states

[Process Management](http://pm2.keymetrics.io/docs/usage/process-management/)

## Process listing

[Process Listing](http://pm2.keymetrics.io/docs/usage/process-management/#process-listing)

## Monitoring CPU/Memory

[Monitoring](http://pm2.keymetrics.io/docs/usage/monitoring/)

## Clustering

[Cluster mode](http://pm2.keymetrics.io/docs/usage/cluster-mode/)

### Hot reload / 0s reload

[Reload without Downtime](http://pm2.keymetrics.io/docs/usage/cluster-mode/#reload-without-downtime)

### Graceful reload

[Graceful Reload](http://pm2.keymetrics.io/docs/usage/cluster-mode/#graceful-reload)

## Logs management

[Log Management](http://pm2.keymetrics.io/docs/usage/log-management/)

## Max Memory Restart

[Max Memory Restart](http://pm2.keymetrics.io/docs/usage/monitoring/#max-memory-restart)

## Startup script

[Startup Script](http://pm2.keymetrics.io/docs/usage/startup/)

## Multiple PM2 on the same server

[Multiple PM2](http://pm2.keymetrics.io/docs/usage/specifics/#multiple-pm2-on-the-same-server)

## Watch & Restart

[Watch and Restart](http://pm2.keymetrics.io/docs/usage/watch-and-restart/)

## JS/JSON app declaration

[Application Declaration](http://pm2.keymetrics.io/docs/usage/application-declaration/)

## Using PM2 in development

[PM2 in Development](http://pm2.keymetrics.io/docs/usage/pm2-development/)

## Run Next generation Javascript

[Run ES6](http://pm2.keymetrics.io/docs/usage/specifics/#enabling-harmony-es6)

# Using PM2 in Cloud Providers

[Using PM2 with PaaS](http://pm2.keymetrics.io/docs/usage/use-pm2-with-cloud-providers/)

# Deployment

[Deployment](http://pm2.keymetrics.io/docs/usage/deployment/)

# Using PM2 programmatically

[PM2 API](http://pm2.keymetrics.io/docs/usage/pm2-api/)

# Special features

[Specifics](http://pm2.keymetrics.io/docs/usage/specifics/)

## Enabling Harmony ES6

[Specifics](http://pm2.keymetrics.io/docs/usage/specifics/)

## CoffeeScript

[Specifics](http://pm2.keymetrics.io/docs/usage/specifics/)

# Knowledge

[Knowledge](http://pm2.keymetrics.io/docs/usage/knowledge/)

# Contributing

[Contributing](http://pm2.keymetrics.io/docs/usage/contributing/)

### User tips from issues
- [Vagrant and pm2 #289](https://github.com/Unitech/pm2/issues/289#issuecomment-42900019)
- [Start the same app on different ports #322](https://github.com/Unitech/pm2/issues/322#issuecomment-46792733)
- [Using ansible with pm2](https://github.com/Unitech/pm2/issues/88#issuecomment-49106686)
- [Cron string as argument](https://github.com/Unitech/pm2/issues/496#issuecomment-49323861)
- [Restart when process reaches a specific memory amount](https://github.com/Unitech/pm2/issues/141)
- [Sticky sessions and socket.io discussion](https://github.com/Unitech/PM2/issues/637)
- [EACCESS - understanding pm2 user/root rights](https://github.com/Unitech/PM2/issues/837)

## External resources and articles

- [Goodbye node-forever, hello pm2](http://devo.ps/blog/goodbye-node-forever-hello-pm2/)
- [https://serversforhackers.com/editions/2014/11/04/pm2/](https://serversforhackers.com/editions/2014/11/04/pm2/)
- http://www.allaboutghost.com/keep-ghost-running-with-pm2/
- http://blog.ponyfoo.com/2013/09/19/deploying-node-apps-to-aws-using-grunt
- http://www.allaboutghost.com/keep-ghost-running-with-pm2/
- http://bioselemental.com/keeping-ghost-alive-with-pm2/
- http://blog.chyld.net/installing-ghost-on-ubuntu-13-10-aws-ec2-instance-with-pm2/
- http://blog.marvinroger.fr/gerer-ses-applications-node-en-production-pm2/
- https://www.codersgrid.com/2013/06/29/pm2-process-manager-for-node-js/
- http://www.z-car.com/blog/programming/how-to-rotate-logs-using-pm2-process-manager-for-node-js
- http://yosoftware.com/blog/7-tips-for-a-node-js/
- https://www.exponential.io/blog/nodeday-2014-moving-a-large-developer-workforce-to-nodejs
- http://blog.rapsli.ch/posts/2013/2013-10-17-node-monitor-pm2.html
- https://coderwall.com/p/igdqyw
- http://revdancatt.com/2013/09/17/node-day-1-getting-the-server-installing-node-and-pm2/
- https://medium.com/tech-talk/e7c0b0e5ce3c

## Contributors

[Contributors](http://pm2.keymetrics.io/hall-of-fame/)

## Sponsors

Thanks to [Devo.ps](http://devo.ps/) and [Wiredcraft](http://wiredcraft.com/) for their knowledge and expertise.

# License

Files in `lib/` are made available under the terms of the GNU Affero General Public License 3.0 (AGPL 3.0).
Except the file `lib/CLI.js` who is made under the terms of the Apache V2 license.


var debug = require('debug')('axm:proxy');

// var cls     = require('continuation-local-storage');
// var ns      = cls.createNamespace('namespace');

var Proxy = module.exports = {
  wrap : function(object, methods, hook) {
    var self = this;

    if (!Array.isArray(methods)) methods = [methods];

    for (var i = 0; i < methods.length; ++i) {
      debug('Wrapping method:', methods[i]);
      var original = object[methods[i]];
      if (!original) return debug('Method %s unknown', methods[i]);
      if (original.__axm_original) {
        debug('Already wrapped', methods[i]);
        if (methods[i] != '_load')
          return;
      }
      var hooked = hook(original);

      if (original.__axm_original) {
        hooked.__axm_original = original.__axm_original;
      }
      else {
        hooked.__axm_original = original;
      }
      object[methods[i]] = hooked;
      //debug('Method proxified');
    }
  }
};


var http = require('http');

http.createServer(function(req, res) {
  res.writeHead(200);
  res.end('hey');
}).listen(8010);
console.log("edit")


var outFile     = pm2_env.pm_out_log_path;

var errFile     = pm2_env.pm_err_log_path;


var axm = require('pmx');

var probe = axm.probe();

var http = require('http');

var meter = probe.meter({
  name    : 'req/min',
  seconds : 60
});

http.createServer(function(req, res) {
  res.writeHead(200);
  meter.mark();
  setTimeout(function() {
    res.end('transaction');
  }, 1000);
}).listen(9010);

setInterval(function() {
  request(['/user', '/bla', '/user/lol/delete', '/POST/POST'][Math.floor((Math.random() * 4))]);
}, 1500);

function makeid()
{
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for( var i=0; i < 5; i++ )
    text += possible.charAt(Math.floor(Math.random() * possible.length));

  return text;
}

function request(path) {
  var options = {
    hostname: '127.0.0.1'
    ,port: 9010
    ,path: path || '/users'
    ,method: 'GET'
    ,headers: { 'Content-Type': 'application/json' }
  };

  var req = http.request(options, function(res) {
    res.setEncoding('utf8');
    res.on('data', function (data) {
      console.log(data); // I can't parse it because, it's a string. why?
    });
  });
  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
  });
  req.end();
}


#!/usr/bin/env bash

SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/include.sh"

cd $file_path/watch

$pm2 start http.js --watch
should '1 should watch be false' 'watch: true' 1

$pm2 stop http
should '2 should watch be false when stopping app' 'watch: false' 1

$pm2 start http
should '3 should watch be false when starting app' 'watch: false' 1

$pm2 restart http.js
should '4 should restart with watch and should be false' 'watch: false' 1

$pm2 delete http

$pm2 start http.js
should '5 should watch be false' 'watch: false' 1

$pm2 stop http.js
should '5 should watch be false' 'watch: false' 1

$pm2 start http.js --watch
should '7 should restart with watch and should be true' 'watch: true' 1

$pm2 delete all

$pm2 start http.js
should '8 should watch be false' 'watch: false' 1

$pm2 restart http.js
should '6 should watch be false' 'watch: false' 1

$pm2 restart http.js --watch
should '7 should restart with watch and should be true' 'watch: true' 1

$pm2 restart http.js --watch
should '8 should restart with watch and should be false' 'watch: false' 1

$pm2 restart http.js --watch
should '9 should restart with watch and should be true' 'watch: true' 1

$pm2 stop http.js
should '10 should stop app and watch is stopped' 'watch: false' 1

$pm2 restart http.js --watch
should '11 should restart stopped app with watch and should be true' 'watch: true' 1

$pm2 restart http.js --watch
should '12 should restart with watch and should be false' 'watch: false' 1

$pm2 kill

$pm2 start app.json
should 'should have started 1 apps' 'online' 1
should 'should have restarted app by name' 'restart_time: 0' 1
should 'should watch be false' 'watch: false' 1

$pm2 restart app.json
should 'should have started 1 apps' 'online' 1
should 'should have restarted app by name' 'restart_time: 1' 1
should 'should watch be false' 'watch: false' 1

$pm2 stop app.json
should 'should have started 1 apps' 'stopped' 1
should 'should have restarted app by name' 'restart_time: 1' 1
should 'should watch be false' 'watch: false' 1

$pm2 kill

$pm2 start app-watch.json
should 'should have started 1 apps' 'online' 1
should 'should have restarted app by name' 'restart_time: 0' 1
should 'should watch exist' 'watch: true' 1

$pm2 stop app-watch.json
should 'should have started 1 apps' 'stopped' 1
should 'should have restarted app by name' 'restart_time: 0' 1
should 'should watch exist' 'watch: false' 1

$pm2 restart app-watch.json
should 'should have started 1 apps' 'online' 1
should 'should have restarted app by name' 'restart_time: 0' 1
should 'should watch exist' 'watch: true' 1

$pm2 restart all
should 'should have started 1 apps' 'online' 1
should 'should have restarted app by name' 'restart_time: 1' 1
should 'should watch exist' 'watch: true' 1

$pm2 stop all
should 'should have started 1 apps' 'stopped' 1
should 'should have restarted app by name' 'restart_time: 1' 1
should 'should watch exist' 'watch: false' 1


keep keep keep keep replace keep keep keep keep

/**
 * Copyright 2013 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.
 */
// Inject custom modules
if (process.env.pmx !== "false") {
  require('pmx').init({
    transactions: process.env.km_link == 'true' && process.env.trace == 'true' || false,
    http: process.env.km_link == 'true' || false,
    v8: process.env.v8 === 'true' || false
  });
}

if (typeof(process.env.source_map_support) != "undefined" &&
    process.env.source_map_support !== "false") {
  require('source-map-support').install();
}

// Cron restart feature
if (process.env.cron_restart) {
  var cron_pattern = process.env.cron_restart;
  var cronJob = require('cron').CronJob;
  var job = new cronJob({
    cronTime: cron_pattern,
    onTick: function () {
      if (process.connected && process.send) {
        process.send({
          'cron_restart': 1
        });
      } else {
        process.exit(0);
      }
    },
    start: false
  });
  job.start();
}

// Rename the process
process.title = process.env.PROCESS_TITLE || 'node ' + process.env.pm_exec_path;

if (process.connected &&
    process.send &&
    process.versions &&
    process.versions.node)
  process.send({
    'node_version': process.versions.node
  });

// uid/gid management
if (process.env.uid || process.env.gid) {

  if (typeof(process.env.uid) === 'string') {
    process.env.HOME = '/home/' + process.env.uid;
    process.env.USER = process.env.uid;
  }

  try {
    if (process.env.gid)
      process.setgid(process.env.gid);
    if (process.env.uid){
      // If no gid specified - set gid to uid
      var new_gid = process.env.gid == null ? process.env.uid : process.env.gid;
      process.initgroups(process.env.uid, new_gid);
      process.setgid(new_gid);
      process.setuid(process.env.uid);
    }
  } catch(e) {
    setTimeout(function() {
      console.error('%s on call %s', e.message, e.syscall);
      console.error('%s is not accessible', process.env.uid);
      return process.exit(1);
    }, 100);
  }
}

// Require the real application
if (process.env.pm_exec_path)
  require('module')._load(process.env.pm_exec_path, null, true);
else
  throw new Error('Could not _load() the script');

// Change some values to make node think that the user's application
// was started directly such as `node app.js`
process.mainModule = process.mainModule || {};
process.mainModule.loaded = false;
require.main = process.mainModule;


/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, options){
  options = options || {};
  if ('string' == typeof val) return parse(val);
  return options.long
    ? long(val)
    : short(val);
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = '' + str;
  if (str.length > 10000) return;
  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
  if (!match) return;
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function short(ms) {
  if (ms >= d) return Math.round(ms / d) + 'd';
  if (ms >= h) return Math.round(ms / h) + 'h';
  if (ms >= m) return Math.round(ms / m) + 'm';
  if (ms >= s) return Math.round(ms / s) + 's';
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function long(ms) {
  return plural(ms, d, 'day')
    || plural(ms, h, 'hour')
    || plural(ms, m, 'minute')
    || plural(ms, s, 'second')
    || ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, n, name) {
  if (ms < n) return;
  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  return Math.ceil(ms / n) + ' ' + name + 's';
}


var axm = require('..');

function fork(script) {
  var app = require('child_process').fork(__dirname + (script || '/fixtures/probe.fixture.js'), []);
  return app;
}

function forkHistogram() {
  var app = require('child_process').fork(__dirname + '/fixtures/histogram.fixture.js', []);
  return app;

}
describe('Probe', function() {
  it('should have the right properties', function(done) {
    axm.should.have.property('probe');

    var probe = axm.probe();

    probe.should.have.property('meter');
    probe.should.have.property('metric');
    probe.should.have.property('histogram');
    probe.should.have.property('counter');
    done();
  });

  it('should fork app and receive data from probes', function(done) {
    var app = fork();

    app.on('message', function(pck) {
      // Will iterate two times, metric change the value to false
      pck.type.should.eql('axm:monitor');

      pck.data.should.have.properties('req/min',
                                      'Realtime user',
                                      'random',
                                      'Cheerio');

      if (pck.data.random.value           && pck.data.random.agg_type == 'sum' &&
          pck.data.Cheerio.value.yes == true && pck.data.Cheerio.agg_type == 'avg' &&
          pck.data.Downloads.value > 1    && pck.data.Downloads.agg_type == 'max') {
        app.kill();
        done();
      }
    });
  });

  it('should receive transposed data', function(done) {
    var app = fork('/fixtures/transpose.fixture.js');
    var pass = 0;

    app.on('message', function(pck) {
      // Will iterate two times, metric change the value to false
      pck.type.should.eql('axm:monitor');

      pck.data.should.have.properties('style_2_docker_config',
                                      'style_1_docker_config');

      if (pck.data.style_1_docker_config.value.val == 'new value' &&
          pck.data.style_2_docker_config.value.val == 'new value') {
        app.kill();
        done();
      }
    });
  });

  it('should fork app and receive data', function(done) {
    var app = forkHistogram();

    app.on('message', function(pck) {
      pck.type.should.eql('axm:monitor');

      if (pck.data.mean && pck.data.mean.agg_type == 'avg' &&
          pck.data.min  && pck.data.min.agg_type == 'min' &&
          pck.data.test && pck.data.test.agg_type == 'sum') {
        app.kill();
        done();
      }
    });
  });

})


* Use of this source code is governed by a license that


var debug     = require('debug')('axm:events');
var Transport = require('./utils/transport.js');
var Common    = require('./common.js');
var stringify = require('json-stringify-safe');

var Events    = {};

Events.emit = function(name, data) {
  if (!name)
    return console.error('[AXM] emit.name is missing');
  if (!data)
    return console.error('[AXM] emit.data is missing');

  var inflight_obj = JSON.parse(stringify(data));

  inflight_obj.__name = name;

  Transport.send({
    type : 'human:event',
    data : inflight_obj
  }, true);
  return false;
};

module.exports = Events;


/**
 * Copyright 2013 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.
 */

var os         = require('os');
var p          = require('path');
var blessed    = require('blessed');
var fs         = require('fs');
var debug      = require('debug')('pm2:monit');
var sprintf    = require('sprintf-js').sprintf;

// Total memory
const totalMem = os.totalmem();

var Dashboard = {};

var DEFAULT_PADDING = {
  top : 0,
  left : 1,
  right : 1
};

var WIDTH_LEFT_PANEL = 30;

/**
 * Synchronous Dashboard init method
 * @method init
 * @return this
 */
Dashboard.init = function() {
  // Init Screen
  this.screen = blessed.screen({
    smartCSR: true,
    fullUnicode: true
  });
  this.screen.title = 'PM2 Dashboard';

  this.list = blessed.list({
    top: '0',
    left: '0',
    width: WIDTH_LEFT_PANEL + '%',
    height: '70%',
    padding: 0,
    scrollbar: {
      ch: ' ',
      inverse: false
    },
    border: {
      type: 'line'
    },
    keys: true,
    autoCommandKeys: true,
    tags: true,
    style: {
      selected: {
        bg: 'blue',
        fg: 'white'
      },
      scrollbar: {
        bg: 'blue',
        fg: 'black'
      },
      fg: 'white',
      border: {
        fg: 'blue'
      },
      header: {
        fg: 'blue'
      }
    }
  });

  this.logBox = blessed.box({
    label: ' Global Logs ',
    top: '0',
    left: WIDTH_LEFT_PANEL + '%',
    width: 100 - WIDTH_LEFT_PANEL + '%',
    height: '70%',
    padding: DEFAULT_PADDING,
    scrollable: true,
    scrollbar: {
      ch: ' ',
      inverse: false
    },
    keys: true,
    autoCommandKeys: true,
    tags: true,
    border: {
      type: 'line'
    },
    style: {
      fg: 'white',
      border: {
        fg: 'white'
      },
      scrollbar: {
        bg: 'blue',
        fg: 'black'
      }
    }
  });

  this.metadataBox = blessed.box({
    label: ' Metadata ',
    top: '70%',
    left: WIDTH_LEFT_PANEL + '%',
    width: 100 - WIDTH_LEFT_PANEL + '%',
    height: '26%',
    padding: DEFAULT_PADDING,
    scrollable: true,
    scrollbar: {
      ch: ' ',
      inverse: false
    },
    keys: true,
    autoCommandKeys: true,
    tags: true,
    border: {
      type: 'line'
    },
    style: {
      fg: 'white',
      border: {
        fg: 'white'
      },
      scrollbar: {
        bg: 'blue',
        fg: 'black'
      }
    }
  });

  this.metricsBox = blessed.list({
    label: ' Custom metrics {#444-fg}(http://bit.ly/code-metrics){/} ',
    top: '70%',
    left: '0%',
    width: WIDTH_LEFT_PANEL + '%',
    height: '26%',
    padding: DEFAULT_PADDING,
    scrollbar: {
      ch: ' ',
      inverse: false
    },
    keys: true,
    autoCommandKeys: true,
    tags: true,
    border: {
      type: 'line'
    },
    style: {
      fg: 'white',
      border: {
        fg: 'white'
      },
      scrollbar: {
        bg: 'blue',
        fg: 'black'
      }
    }
  });

  this.box4 = blessed.text({
    content: ' left/right: switch boards | up/down/mouse: scroll | Ctrl-C: exit{|} {cyan-fg}{bold}To go further check out https://keymetrics.io/{/}  ',
    left: '0%',
    top: '95%',
    width: '100%',
    height: '6%',
    valign: 'middle',
    tags: true,
    style: {
      fg: 'white'
    }
  });

  this.list.focus();

  this.screen.append(this.list);
  this.screen.append(this.logBox);
  this.screen.append(this.metadataBox);
  this.screen.append(this.metricsBox);
  this.screen.append(this.box4);

  this.list.setLabel(' Process list ');

  this.screen.render();

  var that = this;

  var i = 0;
  var boards = ['list', 'logBox', 'metricsBox', 'metadataBox'];
  this.screen.key(['left', 'right'], function(ch, key) {
    (key.name === 'left') ? i-- : i++;
    if (i == 4)
      i = 0;
    if (i == -1)
      i = 3;
    that[boards[i]].focus();
    that[boards[i]].style.border.fg = 'blue';
    if (key.name === 'left') {
      if (i == 3)
        that[boards[0]].style.border.fg = 'white';
      else
        that[boards[i + 1]].style.border.fg = 'white';
    }
    else {
       if (i == 0)
        that[boards[3]].style.border.fg = 'white';
      else
        that[boards[i - 1]].style.border.fg = 'white';
    }
  });

  this.screen.key(['escape', 'q', 'C-c'], function(ch, key) {
    this.screen.destroy();
    process.exit(0);
  });

  // async refresh of the ui
  setInterval(function () {
    that.screen.render();
  }, 300);

  return this;
}

/**
 * Refresh dashboard
 * @method refresh
 * @param {} processes
 * @return this
 */
Dashboard.refresh = function(processes) {
  debug('Monit refresh');

  if(!processes) {
    this.list.setItem(0, 'No process available');
    return;
  }

  if (processes.length != this.list.items.length) {
    this.list.clearItems();
  }

  // Total of processes memory
  var mem = 0;
  processes.forEach(function(proc) {
    mem += proc.monit.memory;
  })

  // Sort process list
  processes.sort(function(a, b) {
    if (a.pm2_env.name < b.pm2_env.name)
      return -1;
    if (a.pm2_env.name > b.pm2_env.name)
      return 1;
    return 0;
  });

  // Loop to get process infos
  for (var i = 0; i < processes.length; i++) {
    // Percent of memory use by one process in all pm2 processes
    var memPercent = (processes[i].monit.memory / mem) * 100;

    // Status of process
    var status = processes[i].pm2_env.status == 'online' ? '{green-fg}' : '{red-fg}';
    status = status + '{bold}' + processes[i].pm2_env.status + '{/}';

    var name = processes[i].pm2_env.name || p.basename(processes[i].pm2_env.pm_exec_path);

    // Line of list
    var item = sprintf('[%2s] %s {|} Mem: {bold}{%s-fg}%3d{/} MB    CPU: {bold}{%s-fg}%2d{/} %s  %s',
                       processes[i].pm2_env.pm_id,
                       name,
                       gradient(memPercent, [255, 0, 0], [0, 255, 0]),
                       (processes[i].monit.memory / 1048576).toFixed(2),
                       gradient(processes[i].monit.cpu, [255, 0, 0], [0, 255, 0]),
                       processes[i].monit.cpu,
                       "%",
                       status);

    // Check if item exist
    if (this.list.getItem(i)) {
      this.list.setItem(i, item);
    }
    else {
      this.list.pushItem(item);
    }

    var proc = processes[this.list.selected];

    this.metadataBox.setLine(0, 'App Name              ' + '{bold}' + proc.pm2_env.name + '{/}');
    this.metadataBox.setLine(1, 'Restarts              ' + proc.pm2_env.restart_time);
    this.metadataBox.setLine(2, 'Uptime                ' + ((proc.pm2_env.pm_uptime && proc.pm2_env.status == 'online') ? timeSince(proc.pm2_env.pm_uptime) : 0));
    this.metadataBox.setLine(3, 'Script path           ' + proc.pm2_env.pm_exec_path);
    this.metadataBox.setLine(4, 'Script args           ' + (proc.pm2_env.args ? (typeof proc.pm2_env.args == 'string' ? JSON.parse(proc.pm2_env.args.replace(/'/g, '"')):proc.pm2_env.args).join(' ') : 'N/A'));
    this.metadataBox.setLine(5, 'Interpreter           ' + proc.pm2_env.exec_interpreter);
    this.metadataBox.setLine(6, 'Interpreter args      ' + (proc.pm2_env.node_args.length != 0 ? proc.pm2_env.node_args : 'N/A'));
    this.metadataBox.setLine(7, 'Exec mode             ' + (proc.pm2_env.exec_mode == 'fork_mode' ? '{bold}fork{/}' : '{blue-fg}{bold}cluster{/}'));
    this.metadataBox.setLine(8, 'Node.js version       ' + proc.pm2_env.node_version);
    this.metadataBox.setLine(9, 'watch & reload        ' + (proc.pm2_env.watch ? '{green-fg}{bold}✔{/}' : '{red-fg}{bold}✘{/}'));
    this.metadataBox.setLine(10, 'Unstable restarts     ' + proc.pm2_env.unstable_restarts);

    this.metadataBox.setLine(11, 'Comment               ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.comment : 'N/A'));
    this.metadataBox.setLine(12, 'Revision              ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.revision : 'N/A'));
    this.metadataBox.setLine(13, 'Branch                ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.branch : 'N/A'));
    this.metadataBox.setLine(14, 'Remote url            ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.url : 'N/A'));
    this.metadataBox.setLine(15, 'Last update           ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.update_time : 'N/A'));

    if (Object.keys(proc.pm2_env.axm_monitor).length != this.metricsBox.items.length) {
      this.metricsBox.clearItems();
    }
    var j = 0;
    for(var monitor in proc.pm2_env.axm_monitor) {
      var prob = '{bold}' + monitor + '{/} {|} ' + proc.pm2_env.axm_monitor[monitor].value;

      if (this.metricsBox.getItem(j)) {
        this.metricsBox.setItem(j, prob);
      }
      else {
        this.metricsBox.pushItem(prob);
      }
      j++;
    }

    this.screen.render();
  }

  return this;
}

/**
 * Put Log
 * @method log
 * @param {} data
 * @return this
 */
Dashboard.log = function(type, data) {
  var that = this;

  // Logs colors
  switch (type) {
    case 'PM2':
      var color = '{blue-fg}';
      break;
    case 'out':
      var color = '{green-fg}';
      break;
    case 'err':
      var color = '{red-fg}';
      break;
    default:
      var color = '{white-fg}';
  }

  var logs = data.data.split('\n');
  logs.forEach(function(log) {
    if (log.length > 0) {
      that.logBox.pushLine(color + data.process.name + '{/} > ' + log);
    }
  });
  if (!this.logBox.focused) {
    this.logBox.setScrollPerc(100);
  }
  return this;
}

module.exports = Dashboard;

function timeSince(date) {

  var seconds = Math.floor((new Date() - date) / 1000);

  var interval = Math.floor(seconds / 31536000);

  if (interval > 1) {
    return interval + 'Y';
  }
  interval = Math.floor(seconds / 2592000);
  if (interval > 1) {
    return interval + 'M';
  }
  interval = Math.floor(seconds / 86400);
  if (interval > 1) {
    return interval + 'D';
  }
  interval = Math.floor(seconds / 3600);
  if (interval > 1) {
    return interval + 'h';
  }
  interval = Math.floor(seconds / 60);
  if (interval > 1) {
    return interval + 'm';
  }
  return Math.floor(seconds) + 's';
}

/* Args :
 *  p : Percent 0 - 100
 *  rgb_ : Array of rgb [255, 255, 255]
 * Return :
 *  Hexa #FFFFFF
 */
function gradient(p, rgb_beginning, rgb_end) {

    var w = (p / 100) * 2 - 1;

    var w1 = (w + 1) / 2.0;
    var w2 = 1 - w1;

    var rgb = [parseInt(rgb_beginning[0] * w1 + rgb_end[0] * w2),
        parseInt(rgb_beginning[1] * w1 + rgb_end[1] * w2),
            parseInt(rgb_beginning[2] * w1 + rgb_end[2] * w2)];

    return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
}


#!/bin/bash

while [ true ]
do
    PM2_PID=`pgrep "pm2: Daemon" -o`

    # Run garbage collector
    kill -SIGILL $PM2_PID
    sleep 5

    FILE="/proc/$PM2_PID/smaps"
    Rss=`echo 0 $(cat $FILE  | grep Rss | awk '{print $2}' | sed 's#^#+#') | bc;`

    echo `date +%H:%M:%S` $Rss >> $RESULT_FILE
    sleep 100
done


if (typeof(process.env.source_map_support) != "undefined" &&

process.env.source_map_support !== "false") {

keep replace replace replace keep keep keep keep keep


###-begin-pm2-completion-###
### credits to npm for the completion file model
#
# Installation: pm2 completion >> ~/.bashrc  (or ~/.zshrc)
#

COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
COMP_WORDBREAKS=${COMP_WORDBREAKS/@/}
export COMP_WORDBREAKS

if type complete &>/dev/null; then
  _pm2_completion () {
    local si="$IFS"
    IFS=$'\n' COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
                           COMP_LINE="$COMP_LINE" \
                           COMP_POINT="$COMP_POINT" \
                           pm2 completion -- "${COMP_WORDS[@]}" \
                           2>/dev/null)) || return $?
    IFS="$si"
  }
  complete -o default -F _pm2_completion pm2
elif type compctl &>/dev/null; then
  _pm2_completion () {
    local cword line point words si
    read -Ac words
    read -cn cword
    let cword-=1
    read -l line
    read -ln point
    si="$IFS"
    IFS=$'\n' reply=($(COMP_CWORD="$cword" \
                       COMP_LINE="$line" \
                       COMP_POINT="$point" \
                       pm2 completion -- "${words[@]}" \
                       2>/dev/null)) || return $?
    IFS="$si"
  }
  compctl -K _pm2_completion + -f + pm2
fi
###-end-pm2-completion-###


#!/bin/bash

if hash systemctl 2> /dev/null; then
    systemctl disable "pm2.service" && \
	systemctl stop "pm2.service" || \
	    echo "pm2 wasn't even running!"
elif hash service 2> /dev/null; then
    service "pm2" stop || echo "pm2 wasn't even running!"
else
    echo "Your system does not appear to use upstart, systemd or sysv, so pm2 could not be stopped"
    echo 'Unless these systems were removed since install, no processes have been left running'
fi


var axm = require('pmx');
axm.http();
var http = require('http');

http.createServer(function(req, res) {
  res.writeHead(200);
  res.end('hoy');
}).listen(8000);