Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nicer defaults #48

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
.DS_Store
93 changes: 49 additions & 44 deletions README.md
Expand Up @@ -9,50 +9,55 @@ clean up all the inter-module references, and without a whole new
## node-supervisor -?


Node Supervisor is used to restart programs when they crash.
It can also be used to restart programs when a *.js file changes.

Usage:
supervisor [options] <program>
supervisor [options] -- <program> [args ...]

Required:
<program>
The program to run.

Options:
-w|--watch <watchItems>
A comma-delimited list of folders or js files to watch for changes.
When a change to a js file occurs, reload the program
Default is '.'

-e|--extensions <extensions>
Specific file extensions to watch in addition to defaults.
Used when --watch option includes folders
Default is 'node|js'

-x|--exec <executable>
The executable that runs the specified program.
Default is 'node'

-n|--no-restart-on error|exit
Don't automatically restart the supervised program if it ends.
Supervisor will wait for a change in the source files.
If "error", an exit code of 0 will still restart.
If "exit", no restart regardless of exit code.

-h|--help|-?
Display these usage instructions.

-q|--quiet
Suppress DEBUG messages

Examples:
supervisor myapp.js
supervisor myapp.coffee
supervisor -w scripts -e myext -x myrunner myapp
supervisor -w lib,server.js,config.js server.js
supervisor -- server.js -h host -p port
Node Supervisor is used to restart programs when they crash.
It can be used to restart programs when a *.js file changes.

Usage:
supervisor [options] <program>
supervisor [options] -- <program> [args ...]

Recommended:
supervisor server.js
Defaults: --no-restart-on error, watches only your <program.js> file be default.

Options:
--watch <list of files/folders>
A comma-seperated list of folders or js files to watch for changes.
When a change to a js file occurs, the server restarts
Defaults to watching your server.js file (whatever the file may be called). -w shortcut

--poll-interval <milliseconds>
How often to poll watched files for changes.
Defaults to 100 milliseconds (node default) -p shortcut

--extensions <file extensions>
Specific file extensions to watch in addition to defaults.
Used when --watch option includes folders
Default is 'node|js' -e shortcut

--exec <executable>
The executable that runs the specified program.
Default is 'node' -x shortcut

--no-restart-on-exit
Never automatically restart the server, regardless of exit code.
-n shortcut (don't forget exit)

--keep-restarting
Whenever the server dies, restart it. May result in the server infinitely restarting.

--help
Display these usage instructions. -h or -? shortcut

--debug
Show DEBUG messages. -d shortcut

Examples:
supervisor myapp.js
supervisor myapp.coffee
supervisor -w scripts -e myext -x myrunner myapp
supervisor -- server.js -h host -p port
supervisor -w server.js --no-restart-on error server.js


## Simple Install
Expand Down
131 changes: 81 additions & 50 deletions lib/supervisor.js
Expand Up @@ -3,20 +3,22 @@ var fs = require("fs");
var spawn = require("child_process").spawn;
var fileExtensionPattern;
var startChildProcess;
var noRestartOn = null;
var debug = true;
var noRestartOn = 'exit';
var debug = false;

require("colors");

exports.run = run;

function run (args) {
var arg, next, watch, program, programArgs, extensions, executor, poll_interval;
while (arg = args.shift()) {
if (arg === "--help" || arg === "-h" || arg === "-?") {
if (arg === "--help" || arg === "-h" || arg === "-?" || arg === '-help') {
return help();
} else if (arg === "--debug" || arg === "-d") {
debug = true;
} else if (arg === "--quiet" || arg === "-q") {
debug = false;
util.debug = function(){};
util.puts = function(){};
debug = false; //assure debugging off. This arg basically doesn't do anything.
} else if (arg === "--watch" || arg === "-w") {
watch = args.shift();
} else if (arg === "--poll-interval" || arg === "-p") {
Expand All @@ -25,8 +27,23 @@ function run (args) {
extensions = args.shift();
} else if (arg === "--exec" || arg === "-x") {
executor = args.shift();
} else if (arg === "--no-restart-on" || arg === "-n") {
noRestartOn = args.shift();
} else if (arg === "--no-restart-on" || arg === '-n') {

var restartArg = args.shift();
if (restartArg === 'exit') {
console.log('node-supervisor defaults to --no-restart-on exit. You can omit this option.'.yellow);
noRestartOn = 'exit'; //assure what was requested.
} else if (restartArg === 'error') {
noRestartOn = 'error';
} else {
console.log('Please pass either \'error\' or \'exit\' (`--no-restart-on exit` is the default though)'.red);
return '';
}

} else if (arg === "--keep-restarting" || arg === '-k') {
noRestartOn = null;
} else if (arg === "--no-restart-on-error" || arg === '-k') {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidentally carried over || arg === '-k', this should be deleted.

noRestartOn = 'error';
} else if (arg === "--") {
// Remaining args are: program [args, ...]
program = args.shift();
Expand All @@ -37,11 +54,12 @@ function run (args) {
program = arg;
}
}

if (!program) {
return help();
}
if (!watch) {
watch = ".";
watch = program;
}
if (!poll_interval) {
poll_interval = 100;
Expand All @@ -63,13 +81,14 @@ function run (args) {
executor = (programExt === "coffee") ? "coffee" : "node";
}

util.puts("")
util.debug("Running node-supervisor with");
util.debug(" program '" + program + "'");
util.debug(" --watch '" + watch + "'");
util.debug(" --extensions '" + extensions + "'");
util.debug(" --exec '" + executor + "'");
util.puts("");
if (debug) {
util.puts("");
util.puts(" program '" + program + "'");
util.puts(" --watch '" + watch + "'");
util.puts(" --extensions '" + extensions + "'");
util.puts(" --exec '" + executor + "'");
util.puts("");
}

// store the call to startProgramm in startChildProcess
// in order to call it later
Expand All @@ -81,15 +100,16 @@ function run (args) {

var watchItems = watch.split(',');
watchItems.forEach(function (watchItem) {
util.puts("Watching " + watchItem + " for changes.");
if (!watchItem.match(/^\/.*/)) { // watch is not an absolute path
// convert watch item to absolute path
watchItem = process.cwd() + '/' + watchItem;
}
util.debug("Watching directory '" + watchItem + "' for changes.");
findAllWatchFiles(watchItem, function(f) {
watchGivenFile( f, poll_interval );
});
});
util.puts("Node will restart on any changes.".green);
};

function print (m, n) { util.print(m+(!n?"\n":"")); return print; }
Expand All @@ -98,68 +118,79 @@ function help () {
print
("")
("Node Supervisor is used to restart programs when they crash.")
("It can also be used to restart programs when a *.js file changes.")
("It can be used to restart programs when a *.js file changes.")
("")
("Usage:")
(" supervisor [options] <program>")
(" supervisor [options] -- <program> [args ...]")
("")
("Required:")
(" <program>")
(" The program to run.")
("Recommended usage:".green.underline)
(" supervisor server.js".green.bold)
(" Defaults: --no-restart-on exit, watches only your <program.js>.")
("")
("Options:")
(" -w|--watch <watchItems>")
(" A comma-delimited list of folders or js files to watch for changes.")
(" When a change to a js file occurs, reload the program")
(" Default is '.'")
(" --watch <list of files/folders>")
(" A comma-seperated list of folders or js files to watch for changes.")
(" When a change to a js file occurs, the server restarts")
(" Defaults to watching your server.js file (whatever the file may be called). -w shortcut")
("")
(" -p|--poll-interval <milliseconds>")
(" --poll-interval <milliseconds>")
(" How often to poll watched files for changes.")
(" Defaults to Node default.")
(" Defaults to 100 milliseconds (node default) -p shortcut")
("")
(" -e|--extensions <extensions>")
(" --extensions <file extensions>")
(" Specific file extensions to watch in addition to defaults.")
(" Used when --watch option includes folders")
(" Default is 'node|js'")
(" Default is 'node|js' -e shortcut")
("")
(" -x|--exec <executable>")
(" --exec <executable>")
(" The executable that runs the specified program.")
(" Default is 'node'")
(" Default is 'node' -x shortcut")
("")
(" --no-restart-on-exit")
(" Never automatically restart the server, regardless of exit code.")
(" -n shortcut (don't forget exit)")
("")
(" -n|--no-restart-on error|exit")
(" Don't automatically restart the supervised program if it ends.")
(" Supervisor will wait for a change in the source files.")
(" If \"error\", an exit code of 0 will still restart.")
(" If \"exit\", no restart regardless of exit code.")
(" --keep-restarting")
(" Whenever the server dies, restart it. May result in the server infinitely restarting.")
("")
(" -h|--help|-?")
(" Display these usage instructions.")
(" --help")
(" Display these usage instructions. -h or -? shortcut")
("")
(" -q|--quiet")
(" Suppress DEBUG messages")
(" --debug")
(" Show DEBUG messages. -d shortcut")
("")
("Examples:")
(" supervisor myapp.js")
(" supervisor myapp.js".green)
(" supervisor myapp.coffee")
(" supervisor -w scripts -e myext -x myrunner myapp")
(" supervisor -- server.js -h host -p port")
(" supervisor -w server.js --no-restart-on error server.js")
("");
};

function startProgram (prog, exec, args) {
if (args)
util.debug("Starting child process with '" + exec + " " + prog + " " + args + "'");
else
util.debug("Starting child process with '" + exec + " " + prog + "'");

if (debug) {
if (args)
util.puts("Starting child process with '" + exec + " " + prog + " " + args + "'");
else
util.puts("Starting child process with '" + exec + " " + prog + "'");
}

var spawnme = args ? [prog].concat(args) : [prog];
crash_queued = false;
var child = exports.child = spawn(exec, spawnme);
child.stdout.addListener("data", function (chunk) { chunk && util.print(chunk); });
child.stderr.addListener("data", function (chunk) { chunk && util.debug(chunk); });
child.stdout.addListener("data", function (chunk) {
chunk && util.print(chunk);
});
child.stderr.addListener("data", function (chunk) {
chunk && util.puts(chunk);
});
child.addListener("exit", function (code) {
if (!crash_queued) {
util.debug("Program " + prog + " exited with code " + code + "\n");
util.puts(prog + " exited with code " + code);
util.puts("Try fixing the problem, save, and see if this error reoccurs\n".yellow);
exports.child = null;
if (noRestartOn == "exit" || noRestartOn == "error" && code !== 0) return;
}
Expand All @@ -177,10 +208,10 @@ function crash () {
var child = exports.child;
setTimeout(function() {
if (child) {
util.debug("crashing child");
util.puts("crashing child");
process.kill(child.pid);
} else {
util.debug("restarting child");
util.puts("restarting child");
startChildProcess();
}
}, 50);
Expand Down
22 changes: 22 additions & 0 deletions node_modules/colors/MIT-LICENSE.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.