From 14c7aa8ba905d6110f93460fcff9a482846636d9 Mon Sep 17 00:00:00 2001 From: indexzero Date: Fri, 24 Dec 2010 15:49:08 -0600 Subject: [PATCH] [api test bin doc] Added stop by script name feature. Improved the cleanlogs functionality. Made event emission consistent. Added to docs --- README.md | 25 +++++++++---- bin/forever | 8 +---- lib/forever.js | 83 ++++++++++++++++++++++++++++---------------- test/forever-test.js | 2 +- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 116f3480..610c9f24 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ There are two distinct ways to use forever: through the command line interface, You can use forever to run any kind of script continuously (whether it is written in node.js or not). The usage options are simple:
-  usage: forever [start | stop | stopall | list] [options] SCRIPT [script options]
+  usage: forever [start | stop | stopall | list | cleanlogs] [options] SCRIPT [script options]
 
   options:
     start          start SCRIPT as a daemon
     stop           stop the daemon SCRIPT
     stopall        stop all running forever scripts
     list           list all running forever scripts
+    cleanlogs      [CAREFUL] Deletes all historical forever log files
 
     -m MAX         Only run the specified script MAX times
     -l  LOGFILE    Logs the forever output to LOGFILE
@@ -105,10 +106,11 @@ Each forever object is an instance of the node.js core EventEmitter. There are s
 
 * error   [err]:          Raised when an error occurs
 * stop    [process]:      Raised when the target script is stopped by the user
-* restart [err, forever]: Raised each time the target script is restarted
-* exit    [err, forever]: Raised when the call to forever.run() completes
-* stdout  [err, data]:    Raised when data is received from the child process' stdout
-* stderr  [err, data]:    Raised when data is received from the child process' stderr
+* save    [path, data]:   Raised when the target Forever object persists the pid information to disk.
+* restart [forever]:      Raised each time the target script is restarted
+* exit    [forever]:      Raised when the call to forever.run() completes
+* stdout  [data]:         Raised when data is received from the child process' stdout
+* stderr  [data]:         Raised when data is received from the child process' stderr
 
 ## Using forever module from node.js
 In addition to using a Forever object, the forever module also exposes some useful methods. Each method returns an instance of an EventEmitter which emits when complete. See the [forever binary script][1] for sample usage.
@@ -119,6 +121,12 @@ Sets the specified configuration (config) for the forever module. In addition to
 * root:    Directory to put all default forever log files 
 * pidPath: Directory to put all forever *.pid files
 
+### forever.start (file, options)
+Starts a script with forever.
+
+### forever.startDaemon (file, options)
+Starts a script with forever as a daemon. WARNING: Will daemonize the current process.
+
 ### forever.stop (index)
 Stops the forever daemon script at the specified index. These indices are the same as those returned by forever.list(). This method returns an EventEmitter that raises the 'stop' event when complete.
 
@@ -131,14 +139,17 @@ Returns a list of metadata objects about each process that is being run using fo
 ### forever.cleanup ()
 Cleans up any extraneous forever *.pid or *.fvr files that are on the target system. This method returns an EventEmitter that raises the 'cleanUp' event when complete.
 
+### forever.cleanLogsSync
+Removes all log files from the root forever directory that do not belong to current running forever processes.
+
 ## Run Tests
-The test coverage for 0.3.0 is currently lacking, but will be improved in 0.3.1.
+The test coverage for 0.3.1 is currently lacking, but will be improved in 0.3.2.
 
   vows test/*-test.js --spec
 
#### Author: [Charlie Robbins](http://www.charlierobbins.com) -#### Contributors: [Fedor Indutny](http://github.com/donnerjack13589) +#### Contributors: [Fedor Indutny](http://github.com/donnerjack13589), [James Halliday](http://substack.net/) [0]: http://nodejitsu.com [1]: https://github.com/indexzero/forever/blob/master/bin/forever diff --git a/bin/forever b/bin/forever index 9448bb0a..ede9ec70 100755 --- a/bin/forever +++ b/bin/forever @@ -99,7 +99,6 @@ var loader = forever.load(config); loader.on('load', function () { var tidy = forever.cleanUp(action === 'cleanlogs'); tidy.on('cleanUp', function () { - // Run all of the files forever if (action) { switch (action) { case 'start': @@ -126,12 +125,7 @@ loader.on('load', function () { break; case 'stop': - if (!(/(\d+)/.test(file))) { - sys.puts(file + ' is not a valid index for a forever process.'); - process.exit(0); - } - - var runner = forever.stop(parseInt(file), true); + var runner = forever.stop(file, true); runner.on('stop', function (process) { sys.puts('Forever stopped process:'); sys.puts(process); diff --git a/lib/forever.js b/lib/forever.js index 1e776c8a..cd6b877f 100644 --- a/lib/forever.js +++ b/lib/forever.js @@ -8,6 +8,7 @@ var sys = require('sys'), fs = require('fs'), + eyes = require('eyes'), colors = require('colors'), path = require('path'), events = require('events'), @@ -17,6 +18,8 @@ var sys = require('sys'), var forever = exports, config; +forever.version = [0, 3, 1]; + // // function load (options, [callback]) // Initializes configuration for forever module @@ -85,31 +88,53 @@ forever.startDaemon = function (file, options) { }; // -// function stop (index) -// Stops the process with the specified -// index in the list of all processes +// function stop (target, [format]) +// Stops the process with the specified index or +// script name in the list of all processes // -forever.stop = function (index, format) { +forever.stop = function (target, format) { var emitter = new events.EventEmitter(), processes = getAllProcesses(), - proc = processes && processes[index]; + results = []; - if (proc) { - process.kill(proc.foreverPid); - process.kill(proc.pid); - - if (format) proc = formatProcess(proc, index, ''); - emitter.emit('stop', proc); + var procs = /(\d+)/.test(target) ? forever.findByIndex(target, processes) + : forever.findByScript(target, processes); + + if (procs && procs.length > 0) { + procs.forEach(function (proc) { + process.kill(proc.foreverPid); + process.kill(proc.pid); + }); + + process.nextTick(function () { + emitter.emit('stop', format ? forever.list(true, procs) : procs); + }); } else { process.nextTick(function () { - emitter.emit('error', new Error('Cannot find forever process with index: ' + index)); + emitter.emit('error', new Error('Cannot find forever process: ' + target)); }); } return emitter; }; +// +// function findByIndex (index, processes) +// Finds the process with the specified index. +// +forever.findByIndex = function (index, processes) { + return processes && [processes[parseInt(index)]]; +}; + +// +// function findByScript (script, processes) +// Finds the process with the specified script name. +// +forever.findByScript = function (script, processes) { + return processes.filter(function (p) { return p.file === script }); +}; + // // function stopAll (format) // Stops all forever processes @@ -119,7 +144,7 @@ forever.stopAll = function (format) { var emitter = new events.EventEmitter(), processes = getAllProcesses() || [], pids = getAllPids(processes); - + if (format) { processes = forever.list(format, processes); } @@ -182,7 +207,7 @@ forever.cleanUp = function (cleanLogs) { var emitter = new events.EventEmitter(), processes = getAllProcesses(true); - if (cleanLogs) forever.cleanLogsSync(); + if (cleanLogs) forever.cleanLogsSync(processes); if (processes && processes.length > 0) { var checked = 0; @@ -223,14 +248,19 @@ forever.cleanUp = function (cleanLogs) { }; // -// function cleanLogsSync () -// Removes all log files from the -// root forever directory +// function cleanLogsSync (processes) +// Removes all log files from the root forever directory +// that do not belong to current running forever processes. +// [processes]: The set of all forever processes // -forever.cleanLogsSync = function () { - var files = fs.readdirSync(config.root); +forever.cleanLogsSync = function (processes) { + var files = fs.readdirSync(config.root), + runningLogs = processes && processes.map(function (p) { return p.logFile.split('/').pop() }); + files.forEach(function (file) { - if (/\.log$/.test(file)) fs.unlinkSync(path.join(config.root, file)); + if (/\.log$/.test(file) && (!runningLogs || runningLogs.indexOf(file) === -1)) { + fs.unlinkSync(path.join(config.root, file)); + } }); }; @@ -441,7 +471,7 @@ Forever.prototype.start = function (restart) { self.times++; if (self.forever || self.times < self.max) { - self.emit('restart', null, self); + self.emit('restart', self); process.nextTick(function () { self.log('Forever restarting script for ' + self.times + ' time'); self.start(true).save(); @@ -451,16 +481,11 @@ Forever.prototype.start = function (restart) { this.running = false; // If had to write to an stdout file, close it - if (self.stdout) { - self.stdout.end(); - } - + if (self.stdout) self.stdout.end(); // If had to write to an stderr file, close it - if (self.stderr) { - self.stderr.end(); - } + if (self.stderr) self.stderr.end(); - self.emit('exit', null, self); + self.emit('exit', self); } }); diff --git a/test/forever-test.js b/test/forever-test.js index d8693de4..07c0dd6b 100644 --- a/test/forever-test.js +++ b/test/forever-test.js @@ -52,7 +52,7 @@ vows.describe('forever').addBatch({ options: [] }); - child.on('exit', this.callback); + child.on('exit', this.callback.bind({}, null)); child.start(); }, "should emit 'exit' when completed": function (err, child) {