Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 200 lines (177 sloc) 6.229 kb
#!/usr/bin/env node
var path = require('path'),
fs = require('fs'),
winston = require('winston'),
sys = require('sys'),
forever = require('./../lib/forever');
var accepts = ['start', 'stop', 'stopall', 'list', 'config', 'clear', 'set', 'cleanlogs', 'restart'], action;
if (accepts.indexOf(process.argv[2]) !== -1) {
action = process.argv.splice(2,1)[0];
}
var argv = require('optimist').boolean(['v', 'verbose', 'a', 'append', 's', 'silent']).argv;
var help = [
'usage: forever [action] [options] SCRIPT [script-options]',
'',
'Monitors the script specified in the current process or as a daemon',
'',
'actions:',
' start Start SCRIPT as a daemon',
' stop Stop the daemon SCRIPT',
' stopall Stop all running forever scripts',
' restart Restart the daemon SCRIPT',
' list List all running forever scripts',
' config Lists all forever user configuration',
' set <key> <val> Sets the specified forever config <key>',
' clear <key> Clears the specified forever config <key>',
' cleanlogs [CAREFUL] Deletes all historical forever log files',
'',
'options:',
' -m MAX Only run the specified script MAX times',
' -l LOGFILE Logs the forever output to LOGFILE',
' -o OUTFILE Logs stdout from child script to OUTFILE',
' -e ERRFILE Logs stderr from child script to ERRFILE',
' -d SOURCEDIR The source directory for which SCRIPT is relative to',
' -p PATH Base path for all forever related files (pid files, etc.)',
' -c COMMAND COMMAND to execute (defaults to node)',
' --pidfile The pid file',
' -a, --append Append logs',
' --minUptime Minimum uptime (millis) for a script to not be considered "spinning"',
' --spinSleepTime Time to wait (millis) between launches of a spinning script. (defaults to killing a spinning script).',
' -v, --verbose Turns on the verbose messages from Forever',
' -s, --silent Run the child script silencing stdout and stderr',
' -h, --help You\'re staring at it',
'',
'[Long Running Process]',
' The forever process will continue to run outputting log messages to the console.',
' ex. forever -o out.log -e err.log my-script.js',
'',
'[Daemon]',
' The forever process will run as a daemon which will make the target process start',
' in the background. This is extremely useful for remote starting simple node.js scripts',
' without using nohup. It is recommended to run start with -o -l, & -e.',
' ex. forever start -l forever.log -o out.log -e err.log my-daemon.js',
' forever stop my-daemon.js',
''
].join('\n');
function isSimpleAction () {
return ['config', 'list', 'stopall', 'cleanlogs'].indexOf(action) !== -1;
};
//
// Show help prompt if requested or if the
// incorrect usage options are supplied
//
if (argv.h || argv.help || (argv._.length === 0 && !isSimpleAction())
&& (!argv.c && !argv.command)) {
sys.puts(help);
return;
}
var mappings = {
'c': 'command',
'e': 'errFile',
'd': 'sourceDir',
'l': 'logFile',
'a': 'appendLog',
'append': 'appendLog',
'm': 'max',
'o': 'outFile',
'p': 'path',
'pidfile': 'pidFile',
's': 'silent',
'silent': 'silent',
'minUptime': 'minUptime',
'spinSleepTime': 'spinSleepTime',
'v': 'verbose',
'verbose': 'verbose'
};
//
// If we are passed more than one non-hyphenated
// options, only use the first one. Assume the
// rest are pass-through for the child process
//
var file = argv._[0], options = {};
if (file) {
//
// Setup pass-thru options for child-process
//
options.options = process.argv.splice(process.argv.indexOf(file)).splice(1);
}
else if (argv.c || argv.command) {
options.options = process.argv.splice(process.argv.indexOf(argv.c || argv.command) + 1);
}
//
// Now that we've removed the target script options
// reparse the options and configure the forever settings
//
argv = require('optimist')(process.argv).boolean(['v', 'verbose', 'a', 'append', 's', 'silent']).argv;
Object.keys(argv).forEach(function (key) {
if (mappings[key] && argv[key]) {
options[mappings[key]] = argv[key];
}
});
if (typeof options['max'] === 'undefined') {
//
// If max isn't specified set it to run forever
//
options.forever = true;
}
if (typeof options['minUptime'] !== 'undefined') {
options['minUptime'] = parseFloat(options['minUptime']);
}
if (typeof options['spinSleepTime'] !== 'undefined') {
options['spinSleepTime'] = parseFloat(options['spinSleepTime']);
}
if (!options.sourceDir) {
//
// Set the sourceDir of the options for graceful
// restarting outside of the main directory
//
options.sourceDir = file && file[0] !== '/' ? process.cwd() : '/';
}
var uid = forever.randomString(24);
options.uid = uid;
options.pidFile = options.pidFile || uid + '.pid';
options.logFile = argv.l || uid + '.log';
//
// Check for existing global config and set each
// key appropriately if it exists.
//
['append', 'silent', 'verbose'].forEach(function (key) {
var target = mappings[key],
value = forever.config.get(key);
if (value) {
options[target] = options[target] || value === 'true';
}
});
//
// Pass the source dir to spawn
//
options.spawnWith = {
cwd: options.sourceDir
};
//
// Configure winston for forever based on the CLI options
//
winston.defaultTransports().console.timestamp = false;
winston.defaultTransports().console.colorize = true;
if (options.verbose) {
winston.defaultTransports().console.level = 'silly';
}
//
// Setup configurations for forever
//
var config = {
root: argv.p
};
//
// Only call `forever.load()` if the root path is different than
// the default root exposed by forever.
//
if (config.root && config.root !== forever.root) {
winston.silly('Loading forever with config: ', config);
forever.load(config);
winston.silly('Loaded forever successfully.');
}
if (action === 'set') {
options = options.options[0];
}
forever.cli.exec(action, file, options);
Jump to Line
Something went wrong with that request. Please try again.