11// Handle input parameters
22var Logger = require ( './eventlog' ) ,
3- optimist = require ( 'optimist ' ) ,
3+ Args = require ( '@author.io/args ' ) ,
44 net = require ( 'net' ) ,
55 max = 60 ,
66 p = require ( 'path' ) ,
7- argv = optimist
8- . demand ( 'file' )
9- . alias ( 'f' , 'file' )
10- . describe ( 'file' , 'The absolute path of the script to be run as a process.' )
11- . check ( function ( argv ) {
12- require ( 'fs' ) . existsSync ( p . resolve ( argv . f ) , function ( exists ) {
13- return exists ;
14- } ) ;
15- } )
16- . describe ( 'scriptoptions' , 'The options to be sent to the script.' )
17- . alias ( 'd' , 'cwd' )
18- . describe ( 'cwd' , 'The absolute path of the current working directory of the script to be run as a process.' )
19- // .check(function(argv){
20- // require('fs').existsSync(p.resolve(argv.d),function(exists){
21- // return exists;
22- // });
23- // })
24- . demand ( 'log' )
25- . alias ( 'l' , 'log' )
26- . describe ( 'log' , 'The descriptive name of the log for the process' )
27- . default ( 'eventlog' , 'APPLICATION' )
28- . alias ( 'e' , 'eventlog' )
29- . describe ( 'eventlog' , 'The event log container. This must be APPLICATION or SYSTEM.' )
30- . default ( 'maxretries' , - 1 )
31- . alias ( 'm' , 'maxretries' )
32- . describe ( 'maxretries' , 'The maximim number of times the process will be auto-restarted.' )
33- . default ( 'maxrestarts' , 5 )
34- . alias ( 'r' , 'maxrestarts' )
35- . describe ( 'maxrestarts' , 'The maximim number of times the process should be restarted within a ' + max + ' second period shutting down.' )
36- . default ( 'wait' , 1 )
37- . alias ( 'w' , 'wait' )
38- . describe ( 'wait' , 'The number of seconds between each restart attempt.' )
39- . check ( function ( argv ) {
40- return argv . w >= 0 ;
41- } )
42- . default ( 'grow' , .25 )
43- . alias ( 'g' , 'grow' )
44- . describe ( 'grow' , 'A percentage growth rate at which the wait time is increased.' )
45- . check ( function ( argv ) {
46- return ( argv . g >= 0 && argv . g <= 1 ) ;
47- } )
48- . default ( 'abortonerror' , 'no' )
49- . alias ( 'a' , 'abortonerror' )
50- . describe ( 'abortonerror' , 'Do not attempt to restart the process if it fails with an error,' )
51- . check ( function ( argv ) {
52- return [ 'y' , 'n' , 'yes' , 'no' ] . indexOf ( argv . a . trim ( ) . toLowerCase ( ) ) >= 0 ;
53- } )
54- . default ( 'stopparentfirst' , 'no' )
55- . alias ( 's' , 'stopparentfirst' )
56- . describe ( 'stopparentfirst' , 'Allow the script to exit using a shutdown message.' )
57- . check ( function ( argv ) {
58- return [ 'y' , 'n' , 'yes' , 'no' ] . indexOf ( argv . a . trim ( ) . toLowerCase ( ) ) >= 0 ;
59- } )
60- . argv ,
61- log = new Logger ( argv . e == undefined ? argv . l : { source :argv . l , eventlog :argv . e } ) ,
627 fork = require ( 'child_process' ) . fork ,
63- script = p . resolve ( argv . f ) ,
64- wait = argv . w * 1000 ,
65- grow = argv . g + 1 ,
668 attempts = 0 ,
679 startTime = null ,
6810 starts = 0 ,
69- child = null
11+ child = null ,
7012 forcekill = false ;
7113
72- if ( argv . d ) {
73- if ( ! require ( 'fs' ) . existsSync ( p . resolve ( argv . d ) ) ) {
74- console . warn ( argv . d + ' not found.' ) ;
75- argv . d = process . cwd ( ) ;
14+ Args . configure ( {
15+ file : {
16+ type : 'string' ,
17+ required : true ,
18+ alias : 'f' ,
19+ description : 'The absolute path of the script to be run as a process.' ,
20+ validate : function ( value ) {
21+ require ( 'fs' ) . existsSync ( p . resolve ( value ) , function ( exists ) {
22+ return exists ;
23+ } ) ;
24+ }
25+ } ,
26+ scriptoptions : {
27+ type : 'string' ,
28+ description : 'The options to be sent to the script.'
29+ } ,
30+ cwd : {
31+ type : 'string' ,
32+ description : 'The absolute path of the current working directory of the script to be run as a process.' ,
33+ alias : 'd' ,
34+ validate : function ( value ) {
35+ require ( 'fs' ) . existsSync ( p . resolve ( value ) , function ( exists ) {
36+ return exists ;
37+ } ) ;
38+ }
39+ } ,
40+ log : {
41+ type : 'string' ,
42+ required : true ,
43+ alias : 'l' ,
44+ description : 'The descriptive name of the log for the process'
45+ } ,
46+ eventlog : {
47+ type : 'string' ,
48+ alias : 'e' ,
49+ description : 'The event log container. This must be APPLICATION or SYSTEM.' ,
50+ defaults : 'APPLICATION'
51+ } ,
52+ maxretries : {
53+ type : 'number' ,
54+ alias : 'm' ,
55+ description : 'The maximim number of times the process will be auto-restarted.' ,
56+ defaults : - 1
57+ } ,
58+ maxrestarts : {
59+ type : 'number' ,
60+ alias : 'r' ,
61+ description : 'The maximim number of times the process should be restarted within a ' + max + ' second period shutting down.' ,
62+ defaults : 5
63+ } ,
64+ wait : {
65+ type : 'number' ,
66+ alias : 'w' ,
67+ description : 'The number of seconds between each restart attempt.' ,
68+ defaults : 1 ,
69+ validate : function ( value ) {
70+ return value >= 0 ;
71+ }
72+ } ,
73+ grow : {
74+ type : 'number' ,
75+ alias : 'g' ,
76+ description : 'A percentage growth rate at which the wait time is increased.' ,
77+ defaults : .25 ,
78+ validate : function ( value ) {
79+ return value >= 0 && value <= 1 ;
80+ }
81+ } ,
82+ abortonerror : {
83+ type : 'string' ,
84+ alias : 'a' ,
85+ description : 'Do not attempt to restart the process if it fails with an error.' ,
86+ defaults : 'no' ,
87+ options : [ 'y' , 'n' , 'yes' , 'no' ]
88+ } ,
89+ stopparentfirst : {
90+ type : 'string' ,
91+ alias : 's' ,
92+ decribe : 'Allow the script to exit using a shutdown message.' ,
93+ defaults : 'no' ,
94+ options : [ 'y' , 'n' , 'yes' , 'no' ]
95+ }
96+ } ) ;
97+ Args . disallowUnrecognized ( ) ;
98+ Args . enforceRules ( ) ;
99+
100+ var argv = Args . data ,
101+ log = new Logger ( argv . eventlog == undefined ? argv . log : { source :argv . log , eventlog :argv . eventlog } ) ,
102+ script = p . resolve ( argv . file ) ,
103+ wait = argv . wait * 1000 ,
104+ grow = argv . grow + 1 ;
105+
106+ if ( argv . cwd ) {
107+ if ( ! require ( 'fs' ) . existsSync ( p . resolve ( argv . cwd ) ) ) {
108+ console . warn ( argv . cwd + ' not found.' ) ;
109+ argv . cwd = process . cwd ( ) ;
76110 }
77- argv . d = p . resolve ( argv . d ) ;
111+ argv . cwd = p . resolve ( argv . cwd ) ;
78112}
79113
80- if ( typeof argv . m === 'string' ) {
81- argv . m = parseInt ( argv . m ) ;
114+ if ( typeof argv . maxretries === 'string' ) {
115+ argv . maxretries = parseInt ( argv . maxretries ) ;
82116}
83117
84118// Set the absolute path of the file
85- argv . f = p . resolve ( argv . f ) ;
119+ argv . file = p . resolve ( argv . file ) ;
86120
87121// Hack to force the wrapper process to stay open by launching a ghost socket server
88122var server = net . createServer ( ) . listen ( ) ;
@@ -100,7 +134,7 @@ var monitor = function() {
100134 if ( ! child || ! child . pid ) {
101135
102136 // If the number of periodic starts exceeds the max, kill the process
103- if ( starts >= argv . r ) {
137+ if ( starts >= argv . maxrestarts ) {
104138 if ( new Date ( ) . getTime ( ) - ( max * 1000 ) <= startTime . getTime ( ) ) {
105139 log . error ( 'Too many restarts within the last ' + max + ' seconds. Please check the script.' ) ;
106140 process . exit ( ) ;
@@ -110,8 +144,8 @@ var monitor = function() {
110144 setTimeout ( function ( ) {
111145 wait = wait * grow ;
112146 attempts += 1 ;
113- if ( attempts > argv . m && argv . m >= 0 ) {
114- log . error ( 'Too many restarts. ' + argv . f + ' will not be restarted because the maximum number of total restarts has been exceeded.' ) ;
147+ if ( attempts > argv . maxretries && argv . maxretries >= 0 ) {
148+ log . error ( 'Too many restarts. ' + argv . file + ' will not be restarted because the maximum number of total restarts has been exceeded.' ) ;
115149 process . exit ( ) ;
116150 } else {
117151 launch ( 'warn' , 'Restarted ' + wait + ' msecs after unexpected exit; attempts = ' + attempts ) ;
@@ -120,7 +154,7 @@ var monitor = function() {
120154 } else {
121155 // reset attempts and wait time
122156 attempts = 0 ;
123- wait = argv . w * 1000 ;
157+ wait = argv . wait * 1000 ;
124158 }
125159} ;
126160
@@ -138,7 +172,7 @@ var launch = function(logLevel, msg) {
138172 return ;
139173 }
140174
141- //log.info('Starting '+argv.f );
175+ //log.info('Starting '+argv.file );
142176 if ( logLevel && msg ) {
143177 log [ logLevel ] ( msg ) ;
144178 }
@@ -156,18 +190,18 @@ var launch = function(logLevel, msg) {
156190 // Fork the child process
157191 var opts = { env :process . env } ;
158192 var args = [ ] ;
159- if ( argv . d ) opts . cwd = argv . d ;
160- if ( argv . s ) opts . detached = true ;
193+ if ( argv . cwd ) opts . cwd = argv . cwd ;
194+ if ( argv . stopparentfirst ) opts . detached = true ;
161195 if ( argv . scriptoptions ) args = argv . scriptoptions . split ( ' ' ) ;
162196 child = fork ( script , args , opts ) ;
163197
164198 // When the child dies, attempt to restart based on configuration
165199 child . on ( 'exit' , function ( code ) {
166- log . warn ( argv . f + ' stopped running.' ) ;
200+ log . warn ( argv . file + ' stopped running.' ) ;
167201
168202 // If an error is thrown and the process is configured to exit, then kill the parent.
169- if ( code !== 0 && argv . a == "yes" ) {
170- log . error ( argv . f + ' exited with error code ' + code ) ;
203+ if ( code !== 0 && argv . abortonerror == "yes" ) {
204+ log . error ( argv . file + ' exited with error code ' + code ) ;
171205 process . exit ( ) ;
172206 //server.unref();
173207 } else if ( forcekill ) {
@@ -183,13 +217,13 @@ var launch = function(logLevel, msg) {
183217var killkid = function ( ) {
184218 forcekill = true ;
185219 if ( child ) {
186- if ( argv . s ) {
220+ if ( argv . stopparentfirst ) {
187221 child . send ( 'shutdown' ) ;
188222 } else {
189223 child . kill ( ) ;
190224 }
191225 } else {
192- log . warn ( 'Attempted to kill an unrecognized process.' )
226+ log . warn ( 'Attempted to kill an unrecognized process.' ) ;
193227 }
194228}
195229
@@ -202,4 +236,4 @@ process.on('uncaughtException', function(err) {
202236} ) ;
203237
204238// Launch the process
205- launch ( 'info' , 'Starting ' + argv . f ) ;
239+ launch ( 'info' , 'Starting ' + argv . file ) ;
0 commit comments