├── .gitignore ├── index.js ├── README.md ├── constants.js ├── example ├── send_command.js └── basic.js ├── LICENSE ├── package.json └── lib └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | *.pid 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = exports = require("./lib"); 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This module is deprecated. 2 | 3 | Use instead: http://pm2.keymetrics.io/docs/usage/pm2-api/ 4 | 5 | -------------------------------------------------------------------------------- /constants.js: -------------------------------------------------------------------------------- 1 | // 2 | // Modifying these values break tests and can break 3 | // pm2-interface intercommunication (because of ports) 4 | // 5 | 6 | var p = require('path'); 7 | var HOME = process.env.PM2_HOME || process.env.HOME; 8 | var DEFAULT_FILE_PATH = p.resolve(HOME, '.pm2'); 9 | 10 | module.exports = { 11 | DAEMON_BIND_HOST : 'localhost', 12 | DAEMON_RPC_PORT : p.join(DEFAULT_FILE_PATH, 'rpc.sock'), // RPC commands 13 | DAEMON_PUB_PORT : p.join(DEFAULT_FILE_PATH, 'pub.sock'), // Realtime events 14 | SUCCESS_EXIT : 0, 15 | ERROR_EXIT : 1 16 | }; 17 | -------------------------------------------------------------------------------- /example/send_command.js: -------------------------------------------------------------------------------- 1 | 2 | var ipm2 = require('..'); 3 | 4 | var ipm2a = ipm2({bind_host : 'localhost'}); 5 | 6 | 7 | 8 | ipm2a.on('ready', function() { 9 | console.log('Connected to pm2'); 10 | 11 | ipm2a.bus.on('*', function(event, data){ 12 | console.log(event); 13 | }); 14 | 15 | setInterval(function() { 16 | 17 | var msg = {type:"god:heap"}; 18 | 19 | ipm2a.rpc.msgProcess({name:"expose_method", msg:msg}, function (err, res) { 20 | if (err) console.log(err) 21 | else console.log(res) 22 | console.log(arguments); 23 | }) 24 | 25 | }, 2000); 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright [2013] [Strzelewicz Alexandre] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pm2-interface", 3 | "version": "2.0.3", 4 | "description": "Interact with pm2 via RPC and receive real time notifications", 5 | "author": { 6 | "name": "Strzelewicz Alexandre", 7 | "email": "as@unitech.io", 8 | "url": "http://unitech.io" 9 | }, 10 | "engines" : { 11 | "node" : ">=0.8" 12 | }, 13 | "main": "index.js", 14 | "dependencies" : { 15 | "pm2-axon" : "2.0.5", 16 | "pm2-axon-rpc" : "0.3.4", 17 | "debug" : "*" 18 | }, 19 | "keywords": [ 20 | "cli", 21 | "fault tolerant", 22 | "sysadmin", 23 | "tools", 24 | "pm2", 25 | "node-pm2", 26 | "monitoring", 27 | "process manager", 28 | "forever", 29 | "process configuration", 30 | "clustering", 31 | "cluster cli", 32 | "cluster", 33 | "cron", 34 | "devops", 35 | "dev ops" 36 | ], 37 | "repository": { 38 | "type" : "git", 39 | "url" : "git://github.com/Unitech/pm2-interface.git" 40 | }, 41 | "license": "Apache v2" 42 | } 43 | -------------------------------------------------------------------------------- /example/basic.js: -------------------------------------------------------------------------------- 1 | var ipm2 = require('..'); 2 | 3 | var ipm2a = ipm2({bind_host : 'localhost'}); 4 | 5 | 6 | 7 | ipm2a.on('ready', function() { 8 | console.log('Connected to pm2'); 9 | 10 | ipm2a.bus.on('*', function(event, data){ 11 | console.log(event); 12 | }); 13 | 14 | // ipm2a.bus.on('log:err', function(event, data){ 15 | // console.log(event, data); 16 | // }); 17 | 18 | // ipm2a.bus.on('log:out', function(event, data){ 19 | // console.log(event, data); 20 | // }); 21 | 22 | 23 | ipm2a.on('rpc_sock:reconnecting', function() { 24 | console.log('rpc_sock:reconnecting'); 25 | }); 26 | ipm2a.on('sub_sock:ready', function() { 27 | console.log('sub_sock:ready'); 28 | }); 29 | ipm2a.on('sub_sock:closed', function() { 30 | console.log('sub_sock:closed'); 31 | }); 32 | 33 | ipm2a.on('sub_sock:reconnecting', function() { 34 | console.log('sub_sock:reconnecting'); 35 | }); 36 | 37 | 38 | // setTimeout(function() { 39 | // ipm2.rpc.restartProcessId(0, function(err, dt) { 40 | // console.log(dt); 41 | // }); 42 | // }, 2000); 43 | 44 | 45 | // ipm2.rpc.getMonitorData({}, function(err, dt) { 46 | // console.log(dt); 47 | // }); 48 | }); 49 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dependencies 3 | */ 4 | 5 | var axon = require('pm2-axon'); 6 | var cst = require('../constants.js'); 7 | var sys = require('sys'); 8 | var rpc = require('pm2-axon-rpc'); 9 | var log = require('debug')('pm2:interface'); 10 | var EventEmitter = require('events').EventEmitter; 11 | 12 | /** 13 | * Export with conf 14 | */ 15 | module.exports = function(opts){ 16 | var sub_port = opts && opts.sub_port || cst.DAEMON_PUB_PORT; 17 | var rpc_port = opts && opts.rpc_port || cst.DAEMON_RPC_PORT; 18 | var bind_host = opts && opts.bind_host || cst.DAEMON_BIND_HOST; 19 | 20 | return new IPM2(sub_port, rpc_port, bind_host); 21 | }; 22 | 23 | /** 24 | * IPM2, Pm2 Interface 25 | */ 26 | 27 | var IPM2 = function(sub_port, rpc_port, bind_host) { 28 | //if (!(this instanceof Bash)) return new Bash(opts); 29 | var self = this; 30 | 31 | EventEmitter.call(this); 32 | 33 | this.sub_port = sub_port; 34 | this.rpc_port = rpc_port; 35 | this.bind_host = bind_host; 36 | 37 | var sub = axon.socket('sub-emitter'); 38 | var sub_sock = this.sub_sock = sub.connect(sub_port); 39 | this.bus = sub; 40 | 41 | var req = axon.socket("req"); 42 | var rpc_sock = this.rpc_sock = req.connect(rpc_port); 43 | this.rpc_client = new rpc.Client(req); 44 | 45 | this.rpc = {}; 46 | 47 | /** 48 | * Disconnect socket connections. This will allow Node to exit automatically. 49 | * Further calls to PM2 from this object will throw an error. 50 | */ 51 | this.disconnect = function () { 52 | self.sub_sock.close(); 53 | self.rpc_sock.close(); 54 | }; 55 | 56 | /** 57 | * Generate method by requesting exposed methods by PM2 58 | * You can now control/interact with PM2 59 | */ 60 | var generateMethods = function(cb) { 61 | log('Requesting and generating RPC methods'); 62 | self.rpc_client.methods(function(err, methods) { 63 | Object.keys(methods).forEach(function(key) { 64 | var method_signature, md; 65 | method_signature = md = methods[key]; 66 | 67 | log('+-- Creating %s method', md.name); 68 | 69 | (function(name) { 70 | self.rpc[name] = function() { 71 | log(name); 72 | var args = Array.prototype.slice.call(arguments); 73 | args.unshift(name); 74 | self.rpc_client.call.apply(self.rpc_client, args); 75 | }; 76 | })(md.name); 77 | 78 | }); 79 | return cb(); 80 | }); 81 | }; 82 | 83 | /** 84 | * Waiting to connect to sub channel 85 | * and RPC 86 | */ 87 | 88 | rpc_sock.on('connect', function() { 89 | log('rpc_sock:ready'); 90 | self.emit('rpc_sock:ready'); 91 | generateMethods(function() { 92 | self.emit('ready'); 93 | }); 94 | }); 95 | 96 | rpc_sock.on('close', function() { 97 | log('rpc_sock:closed'); 98 | self.emit('close'); 99 | }); 100 | 101 | rpc_sock.on('reconnect attempt', function() { 102 | log('rpc_sock:reconnecting'); 103 | self.emit('reconnecting'); 104 | }); 105 | 106 | sub_sock.on('connect', function() { 107 | log('sub_sock ready'); 108 | self.emit('sub_sock:ready'); 109 | }); 110 | 111 | sub_sock.on('close', function() { 112 | log('sub_sock:closed'); 113 | self.emit('closed'); 114 | }); 115 | 116 | sub_sock.on('reconnect attempt', function() { 117 | log('sub_sock:reconnecting'); 118 | self.emit('reconnecting'); 119 | }); 120 | 121 | }; 122 | 123 | sys.inherits(IPM2, EventEmitter); 124 | --------------------------------------------------------------------------------