#136 add smart interpreter selection and execution mode depending on filename extension

This commit is contained in:
tknew2 2013-11-22 13:27:40 +01:00
commit 10d39704ec
15 changed files with 91 additions and 57 deletions

View File

@ -1,4 +1,9 @@
# 0.6.8
- Homogeneize JSON #186
- Auto intepreter selection (you can do pm2 start app.php)
# 0.5.6
- Coffeescript support
@ -11,10 +16,10 @@
- with the --name option when launching file
- with the "name" parameter for JSON files
- Ability to restart a script by name + tests
- Upgrade node-usage to 0.3.8 - fix monitoring feedback for MacOSx
- Upgrade node-usage to 0.3.8 - fix monitoring feedback for MacOSx
- require.main now require the right file (activate it by modifying MODIFY_REQUIRE in constants.js)
- CentOS startup script with pm2 startup centos
- 0 downtime reload
- 0 downtime reload
# 0.5.4

8
examples/echo.php Normal file
View File

@ -0,0 +1,8 @@
<?php
while (1) {
echo 'lol i hate php !';
sleep(1);
}
?>

View File

@ -12,6 +12,7 @@ var Satan = require('./Satan');
var Common = require('./Common');
var cst = require('../constants.js');
var pkg = require('../package.json');
var extItps = require('./interpreter.json');
var CLI = module.exports = {};
require('colors');
@ -35,16 +36,21 @@ CLI.startFile = function(script) {
if (commander.cron)
appConf['cron_restart'] = commander.cron;
if (commander.interpreter)
appConf['exec_interpreter'] = commander.interpreter;
else
appConf['exec_interpreter'] = 'node';
if (commander.executeCommand)
appConf['exec_mode'] = 'fork_mode';
else
appConf['exec_mode'] = 'cluster_mode';
if (commander.interpreter)
appConf['exec_interpreter'] = commander.interpreter;
else if (extItps[path.extname(script)]) {
appConf['exec_interpreter'] = extItps[path.extname(script)];
appConf['exec_mode'] = 'fork_mode';
}
else
appConf['exec_interpreter'] = 'node';
if (commander.startOneTime)
appConf['one_launch_only'] = cst.ONE_LAUNCH_STATUS;
@ -518,6 +524,5 @@ function resolvePaths(appConf) {
console.error(cst.PREFIX_MSG_ERR + app.message);
process.exit(cst.ERROR_EXIT);
}
return app;
}

View File

@ -10,7 +10,7 @@ UX.dispAsTable = function(list) {
head: ["App Name", "id", "mode","PID","status", "port", "Restarted", "Uptime", "memory", "err logs"],
colAligns : ['left', 'left', 'left', 'left','left', 'left', 'right', 'left', 'right']
});
list.forEach(function(l) {
var obj = {};
@ -18,7 +18,7 @@ UX.dispAsTable = function(list) {
var status = l.pm2_env.status;
var port = l.pm2_env.port;
var key = l.pm2_env.name.bold || p.basename(l.pm2_env.pm_exec_path.script).bold;
obj[key] = [
l.pm2_env.pm_id,
mode == 'fork' ? 'fork'.inverse.bold : 'cluster'.blue.bold,

View File

@ -12,7 +12,7 @@ var cst = require('../constants.js');
/**
* Common methods (used by CLI and God)
*/
var Common = module.exports;
/**
@ -25,12 +25,12 @@ var Common = module.exports;
Common.resolveAppPaths = function(app, cwd, outputter) {
var err = Common.validateApp(app, outputter);
if (err)
return err;
cwd = cwd || process.cwd();
app.env = {
pm_cwd: cwd
};
@ -46,7 +46,7 @@ Common.resolveAppPaths = function(app, cwd, outputter) {
if (fs.existsSync(app.pm_exec_path) == false) {
return new Error('script not found : ' + app.pm_exec_path)
return new Error('script not found : ' + app.pm_exec_path);
}
if (app.out_file)
@ -109,6 +109,6 @@ Common.validateApp = function(appConf, outputter) {
return new Error('Cron pattern is not valid !');
}
}
return null;
};
};

View File

@ -141,6 +141,7 @@ function forkMode(pm2_env, cb) {
var spawn = require('child_process').spawn;
var interpreter = pm2_env.exec_interpreter || 'node';
var script = [pm2_env.pm_exec_path];
var out = fs.openSync(pm2_env.pm_out_log_path, 'a');

View File

@ -19,7 +19,7 @@ http.createServer(function (req, res) {
console.log('Access on PM2 monit point %s', path);
if (path == '/') {
// Main monit route
Satan.executeRemote('getMonitorData', {}, function(err, data_proc) {
@ -35,7 +35,7 @@ http.createServer(function (req, res) {
},
processes: data_proc
};
res.write(JSON.stringify(data));
return res.end();
});

View File

@ -1,5 +1,5 @@
// pm2-htop
// Library who interacts with PM2 to display processes resources in htop way
// Library who interacts with PM2 to display processes resources in htop way
// by Strzelewicz Alexandre
var multimeter = require('pm2-multimeter');
@ -24,10 +24,10 @@ var Monit = module.exports = {};
Monit.init = function(processes, debug) {
if (processes === undefined || processes[0] == null)
throw new Error('No processes passed to init');
if (!processes[0].monit)
throw new Error('No monit assigned to processes');
if (processes[0].monit.error)
throw new Error(JSON.stringify(processes[0].monit.error));
@ -46,9 +46,9 @@ Monit.init = function(processes, debug) {
var status = proc.pm2_env.status == 'online' ? '●'.green.bold : '●'.red.bold;
Monit.multi.write(' ' + status + ' ' + process_name.green.bold);
Monit.multi.write('\n');
Monit.multi.write('\n');
Monit.multi.write('[' + proc.pm2_env.pm_id + '] [' + proc.pm2_env.exec_mode + ']\n');
var bar_cpu = Monit.multi(40, (i * 2) + 3 + i, {
width: 30,
solid: {
@ -75,7 +75,7 @@ Monit.init = function(processes, debug) {
bar_cpu.percent(proc.monit.cpu);
Monit.drawRatio(bar_memory, proc.monit.memory);
bars[proc.pid] = {};
bars[proc.pid].memory = bar_memory;
bars[proc.pid].cpu = bar_cpu;
@ -95,7 +95,7 @@ Monit.drawRatio = function(bar_memory, memory) {
else if (memory < RATIO_T2) scale = RATIO_T2;
else if (memory < RATIO_T3) scale = RATIO_T3;
else scale = RATIO_T4;
bar_memory.ratio(memory,
scale,
CliUx.bytesToSize(memory, 3));
@ -104,10 +104,10 @@ Monit.drawRatio = function(bar_memory, memory) {
Monit.refresh = function(dt) {
dt.forEach(function(proc, i) {
if (proc && proc.monit && bars[proc.pid]) {
bars[proc.pid].cpu.percent(proc.monit.cpu);
Monit.drawRatio(bars[proc.pid].memory, proc.monit.memory);
}
});
};

View File

@ -15,27 +15,27 @@ require('coffee-script');
(function ProcessContainer() {
var fs = require('fs');
var worker = require('cluster').worker;
var worker = require('cluster').worker;
var outFile = process.env.pm_out_log_path;
var errFile = process.env.pm_err_log_path;
var pmId = process.env.pm_id;
var pidFile = [process.env.pm_pid_path, pmId, '.pid'].join('');
var script = process.env.pm_exec_path;
var cronRestart = process.env.cron_restart;
if (cst.MODIFY_REQUIRE)
require.main.filename = process.env.pm_exec_path;
fs.writeFileSync(pidFile, process.pid);
process.on('exit', function () {
try {
fs.unlinkSync(pidFile);
}catch(e) {}
});
// Add args to process if args specified on start
if (process.env.args != null)
process.argv = process.argv.concat(eval(process.env.args));
@ -45,7 +45,7 @@ require('coffee-script');
process.title = 'pm2: ' + process.env.name;
exec(script, outFile, errFile);
if (cronRestart)
cronize(cronRestart);
})();
@ -66,7 +66,7 @@ function cronize(cron_pattern) {
}
function exec(script, outFile, errFile) {
// Change dir to fix process.cwd
// Change dir to fix process.cwd
process.chdir(process.env.PWD || p.dirname(script));
var stderr, stdout;
@ -89,7 +89,7 @@ function exec(script, outFile, errFile) {
stdout.write(string);
};
})(process.stdout.write);
process.on('uncaughtException', function(err) {
stderr.write(err.stack);
@ -98,7 +98,7 @@ function exec(script, outFile, errFile) {
type : 'uncaughtException',
stack : err.stack
});
process.exit(cst.CODE_UNCAUGHTEXCEPTION);
});

View File

@ -27,7 +27,7 @@ var cst = require('../constants.js');
var Satan = module.exports = {};
/**
/**
* Code switcher
* It will switch between Daemon part and Client part
*
@ -68,7 +68,7 @@ Satan.onReady = function() {
*/
Satan.remoteWrapper = function() {
if (process.env.SILENT == "true") {
// Redirect output to files
var stdout = fs.createWriteStream(cst.PM2_LOG_FILE_PATH, {
@ -132,12 +132,12 @@ Satan.remoteWrapper = function() {
debug('Daemon lauched bind on port %s addr %s', cst.DAEMON_PUB_PORT, cst.DAEMON_BIND_HOST);
pub.bind(cst.DAEMON_PUB_PORT, cst.DAEMON_BIND_HOST);
God.bus.onAny(function(data) {
debug(this.event);
pub.emit(this.event, data);
});
};
/**
@ -158,7 +158,7 @@ Satan.launchDaemon = function(cb) {
debug('Launching daemon');
var SatanJS = p.resolve(p.dirname(module.filename), 'Satan.js');
var child = require("child_process").fork(SatanJS, [], {
silent : false,
detached : true,
@ -219,7 +219,7 @@ Satan.launchRPC = function() {
Satan.ev = req.connect(cst.DAEMON_RPC_PORT, cst.DAEMON_BIND_HOST);
Satan.ev.on('connect', function() {
debug('Connected to Daemon');
process.emit('satan:client:ready');
});
};

8
lib/interpreter.json Normal file
View File

@ -0,0 +1,8 @@
{
".coffee": "coffee",
".sh": "bash",
".py": "python",
".rb": "ruby",
".php": "php",
".go": "go"
}

View File

@ -16,6 +16,9 @@
}, {
"name" : "Devo.ps",
"email" : "contact@devo.ps"
},{
"name" : "Bret Copeland",
"email" : "bret@atlantisflight.org"
}, {
"name" : "John Hurliman",
"email" : "jhurliman@jhurliman.org"

View File

@ -49,18 +49,15 @@ function ispec {
success "$1"
}
function should()
{
function should {
OUT=`$pm2 prettylist | grep -o "$2" | wc -l`
[ $OUT -eq $3 ] || fail "$1"
success "$1"
}
cd $file_path
########## TEST
############# TEST
echo -e "\033[1mRunning tests:\033[0m"
@ -109,7 +106,7 @@ should 'should app be stopped' 'stopped' 1
$pm2 start test/fixtures/echo.js
should 'should app be online' 'online' 1
cd -
cd -
###############
$pm2 kill
@ -124,7 +121,7 @@ should 'should restart a second time (BY SCRIPT NAME)' 'restart_time: 2' 4
$pm2 restart child
should 'should restart a third time (BY NAME)' 'restart_time: 3' 4
$pm2 reload all
should 'should RELOAD a fourd time' 'restart_time: 4' 4
should 'should RELOAD a fourth time' 'restart_time: 4' 4
########### DELETED STUFF BY ID
@ -132,14 +129,14 @@ $pm2 kill
$pm2 start echo.js
$pm2 delete 0
should 'should has been deleted process by id' '' 0
should 'should has been deleted process by id' "name: 'echo'" 0
########### DELETED STUFF BY NAME
$pm2 kill
$pm2 start echo.js --name test
$pm2 delete test
should 'should has been deleted process by name' '' 0
should 'should has been deleted process by name' "name: 'test'" 0
########### DELETED STUFF BY SCRIPT
$pm2 kill
@ -147,7 +144,7 @@ $pm2 kill
$pm2 start echo.js
$pm2 delete echo.js
$pm2 list
should 'should has been deleted process by script' '' 0
should 'should has been deleted process by script' "name: 'echo'" 0
########### OPTIONS OUTPUT FILES

3
test/fixtures/echo.coffee vendored Normal file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env coffee
setInterval (-> console.log 'ok'), 500

View File

@ -49,13 +49,10 @@ function ispec {
success "$1"
}
function should()
{
function should {
OUT=`$pm2 prettylist | grep -o "$2" | wc -l`
[ $OUT -eq $3 ] || fail "$1"
success "$1"
}
cd $file_path
@ -75,6 +72,13 @@ $pm2 kill
$pm2 start bashscript.sh -x --interpreter bash
should 'should has forked app' 'fork' 1
########### Auto Detective Interpreter In Fork mode
$pm2 kill
$pm2 start echo.coffee -x
should 'should has forked app' 'fork' 1
### Dump resurect should be ok
$pm2 dump