/*
* forever.js: Top level include for the forever module
*
- * (C) 2010 and Charlie Robbins
+ * (C) 2010 Charlie Robbins
* MIT LICENCE
*
*/
@@ -15,13 +15,16 @@
events = require ( 'events' ),
exec = require ( 'child_process' ). exec ,
timespan = require ( 'timespan' ),
+ nconf = require ( 'nconf' ),
daemon = require ( 'daemon' );
-var forever = exports , config ; Export Components / Settings
+var forever = exports ; Export Components / Settings
Export version
and important Prototypes from lib/forever/*
forever . version = [ 0 , 4 , 0 ];
forever . initialized = false ;
-forever . root = path . join ( '/tmp' , 'forever' );
+forever . root = path . join ( process . env . HOME , '.forever' );
+forever . config = new nconf . stores . File ({ file : path . join ( forever . root , 'config.json' ) });
+forever . cli = require ( 'forever/cli' );
forever . Forever = forever . Monitor = require ( 'forever/monitor' ). Monitor ; function load (options, [callback])
@options {Object} Options to load into the forever module
@@ -30,13 +33,21 @@ @options {Object} Options to load into the forever module
options . root = options . root || forever . root ,
options . pidPath = options . pidPath || path . join ( options . root , 'pids' );
If forever is initalized and the config directories are identical
-simply return without creating directories
if ( forever . initialized && forever . config . root === options . root &&
- forever . config . pidPath === options . pidPath ) {
+simply return without creating directories if ( forever . initialized && forever . config . get ( 'root' ) === options . root &&
+ forever . config . get ( 'pidPath' ) === options . pidPath ) {
return ;
}
- forever . config = config = options ;
- Syncronously create the root
directory
+ forever . config = new nconf . stores . File ({ file : path . join ( options . root , 'config.json' ) });
+
Try to load the forever config.json
from
+the specified location.
try {
+ forever . config . loadSync ();
+ }
+ catch ( ex ) { }
+
+ forever . config . set ( 'root' , options . root );
+ forever . config . set ( 'pidPath' , options . pidPath );
+ Syncronously create the root
directory
and the pid
directory for forever. Although there is
an additional overhead here of the sync action. It simplifies
the setup of forever dramatically.
function tryCreate ( dir ) {
@@ -44,27 +55,48 @@ @options {Object} Options to load into the forever module
catch ( ex ) { }
}
- tryCreate ( config . root );
- tryCreate ( config . pidPath );
+ tryCreate ( forever . config . get ( 'root' ));
+ tryCreate ( forever . config . get ( 'pidPath' ));
+ Attempt to save the new config.json
for forever
try {
+ forever . config . saveSync ();
+ }
+ catch ( ex ) { }
+
forever . initialized = true ;
-}; Ensure forever will always be loaded the first time it is required.
function stat (logFile, script, callback)
+}; Ensure forever will always be loaded the first time it is required.
function stat (logFile, script, callback)
@logFile {string} Path to the log file for this script
+@logAppend {boolean} Optional. True Prevent failure if the log file exists.
+
@script {string} Path to the target script.
@callback {function} Continuation to pass control back to
Ensures that the logFile doesn't exist and that
the target script does exist before executing callback.
forever . stat = function ( logFile , script , callback ) {
- fs . stat ( logFile , function ( err , stats ) {
- if ( ! err ) return callback ( new Error ( 'log file ' + logFile + ' exists.' ));
- fs . stat ( script , function ( err , stats ) {
- if ( err ) return callback ( new Error ( 'script ' + script + ' does not exist.' ));
- callback ( null );
+ var logAppend ,
+ realCallback = callback ;
+
+ if ( arguments . length === 4 ) {
+ logAppend = callback ;
+ realCallback = arguments [ 3 ];
+ }
+
+ fs . stat ( script , function ( err , stats ) {
+ if ( err ) return realCallback ( new Error ( 'script ' + script + ' does not exist.' ));
+
+ if ( logAppend ) {
+ realCallback ( null );
+ return ;
+ }
+
+ fs . stat ( logFile , function ( err , stats ) {
+ if ( ! err ) return realCallback ( new Error ( 'log file ' + logFile + ' exists.' ));
+ realCallback ( null );
});
});
-}; function start (script, options)
+}; function start (script, options)
@script {string} Location of the script to run.
@@ -72,31 +104,32 @@ @options {Object} Configuration for forever instance.
Starts a script with forever
forever . start = function ( script , options ) {
return new forever . Monitor ( script , options ). start ();
-}; function startDaemon (script, options)
+}; function startDaemon (script, options)
@script {string} Location of the script to run.
@options {Object} Configuration for forever instance.
Starts a script with forever as a daemon
forever . startDaemon = function ( script , options ) {
- options . logFile = path . join ( config . root , options . logFile || 'forever.log' );
- options . pidFile = path . join ( config . pidPath , options . pidFile );
+ options . logFile = forever . logFilePath ( options . logFile );
+ options . pidFile = forever . pidFilePath ( options . pidFile );
var runner = new forever . Monitor ( script , options );
-
- daemon . daemonize ( options . logFile , options . pidFile , function ( err , pid ) {
+
+ fs . open ( options . logFile , options . appendLog ? 'a+' : 'w+' , function ( err , fd ) {
if ( err ) return runner . emit ( 'error' , err );
- Remark: This should work, but the fd gets screwed up
+
+ var pid = daemon . start ( fd );
+ daemon . lock ( options . pidFile );
Remark: This should work, but the fd gets screwed up
with the daemon process.
process.on('exit', function () {
fs.unlinkSync(options.pidFile);
-});
- process . pid = pid ;
+}); process . pid = pid ;
runner . start ();
});
return runner ;
-}; function stop (target, [format])
+}; function stop (target, [format])
@target {string} Index or script name to stop
@@ -113,8 +146,11 @@ @format {boolean} Indicated if we should CLI format the returned output. if ( procs && procs . length > 0 ) {
procs . forEach ( function ( proc ) {
- process . kill ( proc . foreverPid );
- process . kill ( proc . pid );
+ try {
+ process . kill ( proc . foreverPid );
+ process . kill ( proc . pid );
+ }
+ catch ( ex ) { }
});
process . nextTick ( function () {
@@ -128,7 +164,7 @@ @format {boolean} Indicated if we should CLI format the returned output. }
return emitter ;
-}; function restart (target, format)
+}; function restart (target, format)
@target {string} Index or script name to restart
@@ -141,13 +177,13 @@ @format {boolean} Indicated if we should CLI format the returned output. runner. on ( 'stop' , function ( procs ) {
if ( procs && procs . length > 0 ) {
- async . forEach ( procs , function ( proc , next ) { We need to spawn a new process running the forever CLI
+ async . forEach ( procs , function ( proc , next ) {
We need to spawn a new process running the forever CLI
here because we want each process to daemonize separately
without the main process running forever restart myscript.js
daemonizing itself.
var restartCommand = [
'forever' ,
'start' ,
- '-d' , proc . sourceDir , Remark: Is using a new logfile good behavior?
+ '-d' , proc . sourceDir ,
Remark: Is using a new logfile good behavior?
'-l', path.basename(proc.logFile),
proc . file ,
proc . options . join ( ' ' )
]. join ( ' ' );
@@ -163,12 +199,12 @@ @format {boolean} Indicated if we should CLI format the returned output. emitter. emit ( 'error' , new Error ( 'Cannot find forever process: ' + target ));
}
});
- Bubble up the error to the appropriate EventEmitter instance.
runner . on ( 'error' , function ( err ) {
+ Bubble up the error to the appropriate EventEmitter instance.
runner . on ( 'error' , function ( err ) {
emitter . emit ( 'error' , err );
});
return emitter ;
-}; function findByIndex (index, processes)
+}; function findByIndex (index, processes)
@index {string} Index of the process to find.
@@ -176,7 +212,7 @@ @processes {Array} Set of processes to find in.
Finds the process with the specified index.
forever . findByIndex = function ( index , processes ) {
return processes && [ processes [ parseInt ( index )]];
-}; function findByScript (script, processes)
+}; function findByScript (script, processes)
@script {string} The name of the script to find.
@@ -184,7 +220,7 @@ @processes {Array} Set of processes to find in.
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)
+}; function stopAll (format)
@format {boolean} Value indicating if we should format output
@@ -202,7 +238,10 @@ @format {boolean} Value indicating if we should format output
cPids = pids . map ( function ( pid ) { return pid . pid });
fPids . concat ( cPids ). forEach ( function ( pid ) {
- process . kill ( pid );
+ try {
+ process . kill ( pid );
+ }
+ catch ( ex ) { }
});
process . nextTick ( function () {
@@ -216,28 +255,32 @@ @format {boolean} Value indicating if we should format output
}
return emitter ;
-}; function list (format)
+}; function list (format, procs)
@format {boolean} If set, will return a formatted string of data
+@procs {Array} Set of processes to list format.
+
Returns the list of all process data managed by forever.
forever . list = function ( format , procs ) {
- var formatted = [], procs = procs || getAllProcesses ();
+ var formatted = [];
+
+ procs = procs || getAllProcesses ();
if ( ! procs ) return null ;
if ( format ) {
- var index = 0 , maxLen = 0 ; Iterate over the procs to see which has the longest options string
procs . forEach ( function ( proc ) {
+ var index = 0 , maxLen = 0 ; Iterate over the procs to see which has the longest options string
procs . forEach ( function ( proc ) {
proc . length = [ proc . file ]. concat ( proc . options ). join ( ' ' ). length ;
if ( proc . length > maxLen ) maxLen = proc . length ;
});
- procs . forEach ( function ( proc ) { Create padding string to keep output aligned
var padding = new Array ( maxLen - proc . length + 1 ). join ( ' ' );
+ procs . forEach ( function ( proc ) { Create padding string to keep output aligned
var padding = new Array ( maxLen - proc . length + 1 ). join ( ' ' );
formatted . push ( formatProcess ( proc , index , padding ));
index ++ ;
});
}
return format ? formatted . join ( '\n' ) : procs ;
-}; function cleanUp ()
+}; function cleanUp ()
Utility function for removing excess pid and
config, and log files used by forever.
forever . cleanUp = function ( cleanLogs ) {
@@ -253,10 +296,10 @@ @format {boolean} If set, will return a formatted string of data
checkProcess ( proc . foreverPid , function ( manager ) {
if ( ! child && ! manager || proc . dead ) {
if ( proc . pidFile ) {
- fs . unlink ( proc . pidFile , function () { Ignore errors
});
+ fs . unlink ( proc . pidFile , function () { Ignore errors
});
}
- fs . unlink ( path . join ( config . pidPath , proc . foreverPid + '.fvr' ), function () { Ignore errors
});
+ fs . unlink ( path . join ( forever . config . get ( 'pidPath' ), proc . uid + '.fvr' ), function () { Ignore errors
});
if ( cleanLogs ) {
fs . unlink ( proc . logFile , function () { /* Ignore Errors */ });
@@ -278,21 +321,22 @@ @format {boolean} If set, will return a formatted string of data
}
return emitter ;
-}; function cleanLogsSync (processes)
+}; function cleanLogsSync (processes)
@processes {Array} The set of all forever processes
Removes all log files from the root forever directory
that do not belong to current running forever processes.
forever . cleanLogsSync = function ( processes ) {
- var files = fs . readdirSync ( config . root ),
- runningLogs = processes && processes . map ( function ( p ) { return p . logFile . split ( '/' ). pop () });
+ var files = fs . readdirSync ( forever . config . get ( 'root' )),
+ running = processes && processes . filter ( function ( p ) { return p && p . logFile }),
+ runningLogs = running && running . map ( function ( p ) { return p . logFile . split ( '/' ). pop () });
files . forEach ( function ( file ) {
if ( /\.log$/ . test ( file ) && ( ! runningLogs || runningLogs . indexOf ( file ) === - 1 )) {
- fs . unlinkSync ( path . join ( config . root , file ));
+ fs . unlinkSync ( path . join ( forever . config . get ( 'root' ), file ));
}
});
-}; function randomString (bits)
+}; function randomString (bits)
@bits {Number} Bit-length of the base64 string to return.
@@ -301,13 +345,33 @@ @bits {Number} Bit-length of the base64 string to return.
length ⌈bits/6⌉ of characters from the base64 alphabet. forever . randomString = function ( bits ) {
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+' ,
rand , i , ret = '' ;
- in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
while ( bits > 0 ) {
- rand = Math . floor ( Math . random () * 0x100000000 ) // 32-bit integer base 64 means 6 bits per character, so we use the top 30 bits from rand to give 30/6=5 characters.
for ( i = 26 ; i > 0 && bits > 0 ; i -= 6 , bits -= 6 ) {
+ in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
while ( bits > 0 ) {
+ rand = Math . floor ( Math . random () * 0x100000000 ) // 32-bit integer base 64 means 6 bits per character, so we use the top 30 bits from rand to give 30/6=5 characters.
for ( i = 26 ; i > 0 && bits > 0 ; i -= 6 , bits -= 6 ) {
ret += chars [ 0x3F & rand >>> i ];
}
}
return ret ;
-}; function checkProcess (pid, callback)
+}; function logFilePath (logFile)
+
+@logFile {string} Log file path
+
+Determines the full logfile path name
forever . logFilePath = function ( logFile , uid ) {
+ if ( logFile && logFile [ 0 ] === '/' ) {
+ return logFile ;
+ } else {
+ return path . join ( forever . config . get ( 'root' ), logFile || ( uid || 'forever' ) + '.log' );
+ }
+}; function pidFilePath (pidFile)
+
+@logFile {string} Pid file path
+
+Determines the full pid file path name
forever . pidFilePath = function ( pidFile ) {
+ if ( pidFile && pidFile [ 0 ] === '/' ) {
+ return pidFile ;
+ } else {
+ return path . join ( forever . config . get ( 'pidPath' ), pidFile );
+ }
+}; function checkProcess (pid, callback)
@pid {string} pid of the process to check
@@ -318,7 +382,7 @@ @callback {function} Continuation to pass control backto.
if ( err ) return callback ( false );
callback ( stdout . indexOf ( pid ) !== - 1 );
});
-}; function formatProcess (proc index, padding)
+}; function formatProcess (proc index, padding)
@proc {Object} Process to format
@@ -327,40 +391,37 @@ @index {Number} Index of the process in the set of all processes
@padding {string} Padding to add to the formatted output
Returns a formatted string for the process @proc at
-the specified index.
function formatProcess ( proc , index , padding ) { Create an array of the output we can later join
return [ ' [' + index + ']' , proc . file . green ]
- . concat ( proc . options . map ( function ( opt ) { return opt . green }))
+the specified index. function formatProcess ( proc , index , padding ) { Create an array of the output we can later join
return [ ' [' + index + ']' , proc . file . grey ]
+ . concat ( proc . options . map ( function ( opt ) { return opt . grey }))
. concat ([ padding + '[' + proc . pid + ',' , proc . foreverPid + ']' ])
- . concat ( proc . logFile . magenta )
+ . concat ( proc . logFile ? proc . logFile . magenta : '' )
. concat ( timespan . fromDates ( new Date ( proc . ctime ), new Date ()). toString (). yellow )
. join ( ' ' );
-}; function getAllProcess ([findDead])
+}; function getAllProcess ([findDead])
@findDead {boolean} Optional parameter that indicates to return dead procs
Returns all data for processes managed by forever.
function getAllProcesses ( findDead ) {
var results = [], processes = {},
- files = fs . readdirSync ( config . pidPath );
+ files = fs . readdirSync ( forever . config . get ( 'pidPath' ));
if ( files . length === 0 ) return null ;
files . forEach ( function ( file ) {
try {
- var fullPath = path . join ( config . pidPath , file ),
+ var fullPath = path . join ( forever . config . get ( 'pidPath' ), file ),
data = fs . readFileSync ( fullPath ). toString ();
- switch ( file . match ( /\.(\w{3})$/ )[ 1 ]) {
- case 'pid' :
- var pid = parseInt ( data );
- if ( ! processes [ pid ]) processes [ pid ] = { foreverPid : pid };
- break ;
-
- case 'fvr' :
+ switch ( path . extname ( file )) { case '.pid':
+ var pid = parseInt(data);
+ if (!processes[pid]) processes[pid] = { foreverPid: pid };
+ break;
case '.fvr' :
var child = JSON . parse ( data );
- processes [ child . foreverPid ] = child ;
+ processes [ child . pid ] = child ;
break ;
}
}
- catch ( ex ) { Ignore errors
Ignore errors
}
});
Object . keys ( processes ). forEach ( function ( key ) {
@@ -370,7 +431,7 @@ @findDead {boolean} Optional parameter that indicates to return dead procs
});
return results ;
-}; function getAllPids ()
+}; function getAllPids ()
Returns the set of all pids managed by forever.
e.x. [{ pid: 12345, foreverPid: 12346 }, ...]
function getAllPids ( processes ) {
diff --git a/docs/forever/cli.html b/docs/forever/cli.html
new file mode 100644
index 00000000..ec5e6e87
--- /dev/null
+++ b/docs/forever/cli.html
@@ -0,0 +1,224 @@
+ cli.js
cli.js /*
+ * cli.js: Handlers for the forever CLI commands.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var sys = require ( 'sys' ),
+ path = require ( 'path' ),
+ eyes = require ( 'eyes' ),
+ winston = require ( 'winston' ),
+ forever = require ( 'forever' );
+
+var cli = exports ;
+
+var reserved = [ 'root' , 'pidPath' ];
+
+var inspect = eyes . inspector ({ stream : null ,
+ styles : { // Styles applied to stdout
+ all : null , // Overall style applied to everything
+ label : 'underline' , // Inspection labels, like 'array' in `array: [1, 2, 3]`
+ other : 'inverted' , // Objects which don't have a literal representation, such as functions
+ key : 'grey' , // The keys in object literals, like 'a' in `{a: 1}`
+ special : 'grey' , // null, undefined...
+ number : 'blue' , // 1, 2, 3, etc
+ bool : 'magenta' , // true false
+ regexp : 'green' , // /\d+/
+ string : 'yellow'
+ }
+}); function exec (action, file, options)
+
+@action {string} CLI action to execute
+
+@file {string} Location of the target forever script or process.
+
+@options {Object} Options to pass to forever for the action
.
+
+Executes the action
in forever with the specified file
and options
.
cli . exec = function ( action , file , options ) {
+ winston . info ( 'Running action: ' + action . yellow );
+
+ winston . silly ( 'Tidying ' + forever . config . get ( 'root' ));
+ var tidy = forever . cleanUp ( action === 'cleanlogs' );
+ tidy . on ( 'cleanUp' , function () {
+ winston . silly ( forever . config . get ( 'root' ) + ' tidied.' );
+
+ if ( file && action !== 'set' && action !== 'clear' ) {
+ winston . info ( 'Forever processing file: ' + file . magenta );
+ }
+
+ if ( options ) {
+ winston . silly ( 'Forever using options' , options );
+ } If there is no action then start in the current
+process with the specified file
and options
.
if ( ! action ) {
+ return cli . start ( file , options );
+ }
+ else if ( action === 'cleanlogs' ) {
+ return ;
+ }
+
+ var daemon = true ;
+ cli [ action ]( file , options , daemon );
+ });
+}; function start (file, options, daemon)
+
+@file {string} Location of the script to spawn with forever
+
+@options {Object} Options to spawn the script file
with.
+
+@daemon {boolean} Value indicating if we should spawn as a daemon
+
+Starts a forever process for the script located at file
with the
+specified options
. If daemon
is true, then the script will be
+started as a daemon process.
cli . start = function ( file , options , daemon ) {
+ tryStart ( file , options , function () {
+ return daemon
+ ? forever . startDaemon ( file , options )
+ : forever . start ( file , options );
+ });
+}; function stop (file)
+
+@file {string} Target forever process to stop
+
+Stops the forever process specified by file
.
cli . stop = function ( file ) {
+ var runner = forever . stop ( file , true );
+
+ runner . on ( 'stop' , function ( process ) {
+ winston . info ( 'Forever stopped process:' );
+ sys . puts ( process );
+ });
+
+ runner . on ( 'error' , function ( err ) {
+ winston . error ( 'Forever cannot find process with index: ' + file )
+ });
+}; function stopall ()
+
+Stops all currently running forever processes.
cli . stopall = function () {
+ var runner = forever . stopAll ( true );
+ runner . on ( 'stopAll' , function ( processes ) {
+ if ( processes ) {
+ winston . info ( 'Forever stopped processes:' );
+ sys . puts ( processes );
+ }
+ else {
+ winston . info ( 'No forever processes running' );
+ }
+ });
+}; function restart (file)
+
+@file {string} Target process to restart
+
+Restarts the forever process specified by file
.
cli . restart = function ( file ) {
+ var runner = forever . restart ( file , true );
+ runner . on ( 'restart' , function ( processes ) {
+ if ( processes ) {
+ winston . info ( 'Forever restarted processes:' );
+ sys . puts ( processes );
+ }
+ else {
+ winston . info ( 'No forever processes running' );
+ }
+ });
+}; function list ()
+
+Lists all currently running forever processes.
cli . list = function () {
+ var processes = forever . list ( true );
+ if ( processes ) {
+ winston . info ( 'Forever processes running' );
+ sys . puts ( processes );
+ }
+ else {
+ winston . info ( 'No forever processes running' );
+ }
+}; function config ()
+
+Lists all of the configuration in ~/.forever/config.json
.
cli . config = function () {
+ var keys = Object . keys ( forever . config . store ),
+ conf = inspect ( forever . config . store );
+
+ if ( keys . length <= 2 ) {
+ conf = conf . replace ( /\{\s/ , '{ \n' )
+ . replace ( /\}/ , '\n}' )
+ . replace ( '\033[90m' , ' \033[90m' )
+ . replace ( /, /ig , ',\n ' )
+ }
+ else {
+ conf = conf . replace ( /\n\s{4}/ig , '\n ' );
+ }
+
+ conf . split ( '\n' ). forEach ( function ( line ) {
+ winston . info ( line );
+ });
+}; function set (key, value)
+
+@key {string} Key to set in forever config
+
+@value {string} Value to set for key
+
+Sets the specified key
/ value
pair in the
+forever user config.
cli . set = function ( key , value ) {
+ if ( ! key || ! value ) {
+ return winston . error ( 'Both <key> and <value> are required.' );
+ }
+
+ updateConfig ( function () {
+ winston . info ( 'Setting forever config: ' + key . grey );
+ forever . config . set ( key , value );
+ });
+}; function clear (key)
+
+@key {string} Key to remove from ~/.forever/config.json
+
+Removes the specified key
from the forever user config.
cli . clear = function ( key ) {
+ if ( reserved . indexOf ( key ) !== - 1 ) {
+ winston . warn ( 'Cannot clear reserved config: ' + key . grey );
+ winston . warn ( 'Use `forever set ' + key + '` instead' );
+ return ;
+ }
+
+ updateConfig ( function () {
+ winston . info ( 'Clearing forever config: ' + key . grey );
+ forever . config . clear ( key );
+ });
+}; function (file, options, callback)
+
+@file {string} Target script to start
+
+@options {Object} Options to start the script with
+
+@callback {function} Continuation to respond to when complete.
+
+Helper function that sets up the pathing for the specified file
+then stats the appropriate files and responds.
function tryStart ( file , options , callback ) {
+ var fullLog , fullScript
+
+ fullLog = forever . logFilePath ( options . logFile , options . uid );
+ fullScript = path . join ( options . sourceDir , file );
+
+ forever . stat ( fullLog , fullScript , options . appendLog , function ( err ) {
+ if ( err ) {
+ winston . error ( 'Cannot start forever: ' + err . message );
+ process . exit ( - 1 );
+ }
+
+ callback ();
+ });
+} function updateConfig (updater)
+
+@updater {function} Function which updates the forever config
+
+Helper which runs the specified updater
and then saves the forever
+config to forever.config.get('root')
.
function updateConfig ( updater ) {
+ updater ();
+ forever . config . save ( function ( err ) {
+ if ( err ) {
+ return winston . error ( 'Error saving config: ' + err . message );
+ }
+
+ cli . config ();
+ winston . info ( 'Forever config saved: ' + path . join ( forever . config . get ( 'root' ), 'config.json' ). yellow );
+ });
+}
+
+
\ No newline at end of file
diff --git a/docs/forever/monitor.html b/docs/forever/monitor.html
index 60fa9fae..1059f86a 100644
--- a/docs/forever/monitor.html
+++ b/docs/forever/monitor.html
@@ -1,7 +1,7 @@
- monitor.js
monitor.js /*
+ monitor.js
monitor.js /*
* monitor.js: Core functionality for the Monitor object.
*
- * (C) 2010 and Charlie Robbins
+ * (C) 2010 Charlie Robbins
* MIT LICENCE
*
*/
@@ -20,16 +20,17 @@ @options {Object} Configuration for this instance.
Creates a new instance of forever with specified params.
var Monitor = exports . Monitor = function ( script , options ) {
events . EventEmitter . call ( this );
-
+
this . silent = options . silent || false ;
this . forever = options . forever || false ;
this . command = options . command || 'node' ;
this . sourceDir = options . sourceDir ;
this . options = options . options || [];
this . spawnWith = options . spawnWith || null ;
+ this . uid = options . uid || forever . randomString ( 24 );
this . max = options . max ;
- this . logFile = options . logFile ;
- this . pidFile = options . pidFile ;
+ this . logFile = options . logFile || path . join ( forever . config . get ( 'root' ), this . uid + '.log' );
+ this . pidFile = options . pidFile || path . join ( forever . config . get ( 'pidPath' ), this . uid + '.pid' );
this . outFile = options . outFile ;
this . errFile = options . errFile ;
this . logger = options . logger || new ( winston . Logger )({
@@ -82,8 +83,12 @@ @restart {boolean} Value indicating whether this is a restart.
this . ctime = Date . now ();
this . child = child ;
this . running = true ;
- this . emit ( restart ? 'restart' : 'start' , self );
- this . save ()
+
+ this . once ( 'save' , function () {
+ self . emit ( restart ? 'restart' : 'start' , self );
+ });
+
+ this . save ();
Hook all stream data and process it
function listenTo ( stream ) {
child [ stream ]. on ( 'data' , function ( data ) {
if ( ! self . silent && ! self [ stream ]) { If we haven't been silenced, and we don't have a file stream
@@ -145,6 +150,7 @@
@restart {boolean} Value indicating whether this is a restart.
}
var childData = {
+ uid : this . uid ,
ctime : this . ctime ,
pid : this . child . pid ,
foreverPid : process . pid ,
@@ -162,8 +168,8 @@ @restart {boolean} Value indicating whether this is a restart.
childData . file = childData . file . replace ( this . sourceDir + '/' , '' );
}
- var childPath = path . join ( forever . config . pidPath , childData . foreverPid + '.fvr' );
- fs . writeFile ( childPath , JSON . stringify ( childData ), function ( err ) {
+ var childPath = path . join ( forever . config . get ( 'pidPath' ), this . uid + '.fvr' );
+ fs . writeFile ( childPath , JSON . stringify ( childData , null , 2 ), function ( err ) {
if ( err ) self . emit ( 'error' , err );
self . emit ( 'save' , childPath , childData );
});