File Coverage

blib/lib/NetSDS/App.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # MODULE: NetSDS::App
4             #
5             # DESCRIPTION: Common NetSDS application framework
6             #
7             # AUTHOR: Michael Bochkaryov (Rattler),
8             # COMPANY: Net.Style
9             #
10             #===============================================================================
11              
12             =head1 NAME
13              
14             B - common application superclass
15              
16             =head1 SYNOPSIS
17              
18             #!/usr/bin/env perl
19            
20             use 5.8.0;
21             use warnings;
22             use strict;
23              
24             MyApp->run(
25             conf_file => '/etc/NetSDS/myapp.conf', # default place for config search
26             daemon => 1, # run in daemon mode
27             use_pidfile => 1, # write PID file to avoid double processing
28             verbose => 0, # no verbosity
29             );
30              
31             1;
32              
33             # Application logic here
34             package MyApp;
35              
36             use base 'NetSDS::App';
37              
38             # Startup hook
39             sub start {
40             my ($self) = @_;
41              
42             # Use configuration
43             $self->{listen_port} = $self->conf->{listen_port};
44              
45             # Use logging subsystem
46             $self->log("info", "Application successfully started with PID=".$self->pid);
47             }
48              
49             # Main processing hook
50             sub process {
51             my ($self) = @_;
52             print "Hello!";
53              
54             # Use verbose output
55             $self->speak("Trying to be more verbose");
56              
57             }
58              
59             =head1 DESCRIPTION
60              
61             C is a base class for NetSDS applications.
62             It implements common functionality including the following:
63              
64             * initialization
65             * configuration file processing
66             * command line parameters processing
67             * application workflow
68             * daemonization
69             * PID file processing
70             * logging
71             * event detail records writing
72             * default signal handling
73              
74             New application should be inherited from C class
75             directly or via child classes for more specific tasks like
76             CGI, AGI, SMPP and other.
77              
78             Common application workflow is described on this diagram:
79              
80             App->run(%params)
81             |
82             initialize()
83             |
84             ----------
85             | |
86             start() |
87             | |
88             process() --- main_loop()
89             | |
90             stop() |
91             | |
92             ----------
93             |
94             finalize()
95              
96             When application is starting C method is invoked first.
97             It provides common start time functionality like CLI parameters processing,
98             daemonization, reading configuration.
99              
100             C method may be overwritten in more specific frameworks
101             to change default behaviour of some application types.
102              
103             Then C method invoked to process main application logic.
104             This method provides three redefinable hooks: C, C and C.
105             Theese hooks should be overwritten to implement necessary logic.
106              
107             =over
108              
109             =item * B - start time hook
110              
111             =item * B - process iteration hook
112              
113             =item * B - finish time hook
114              
115             =back
116              
117             Depending on C flag main_loop() may call process() hook
118             in infinite loop or only once.
119              
120             C workflow may be redefined in inherited framework to implement
121             some other process flow logic.
122              
123             On the last step C method is invoked to make necessary
124             finalization actions on framework level.
125              
126             =head1 STARTUP PARAMETERS
127              
128             Application class may be provided with a number of parameters that allows to manage application behaviour.
129             For example it may be a configuration file, daemonization mode or debugging flag.
130              
131             Such parameters are passed to run() method as hash:
132              
133             MyApp->run(
134             has_conf => 1,
135             conf_file => '/etc/sample/file.conf',
136             daemon => 1,
137             use_pidfile => 1,
138             );
139              
140             =over
141              
142             =item * B - 1 if configuration file is required (default: yes)
143              
144             Mostly our applications requires configuration files but some of them
145             doesn't require any configuration (e.g. small utilities, etc).
146             Set C parameter to 0 to avoid search of configuration file.
147              
148             =item * B - default path to configuration file (default: autodetect)
149              
150             This parameter allows to set explicitly path to configuration file.
151             By default it's determined from application name and is looking like
152             C
153              
154             =item * B - application name (default: autodetect)
155              
156             This name is used for config and PID file names, logging.
157             By default it's automatically detected by executable script name.
158              
159             =item * B - 1 for debugging flag (default: no)
160              
161             =item * B - 1 for daemon mode (default: no)
162              
163             =item * B - 1 for verbose mode (default: no)
164              
165             =item * B - 1 to use PID files (default: no)
166              
167             =item * B - path to PID files catalog (default: '/var/run/NetSDS')
168              
169             =item * B - 1 for auto features inclusion (default: no)
170              
171             This parameter should be set to 1 if you plan to use automatically plugged
172             application features. Read C section below.
173              
174             =item * B - 1 for inifinite loop (default: yes)
175              
176             =item * B - EDR (event detail records) file name (default: undef)
177              
178             =back
179            
180             =head1 COMMAND LINE PARAMETERS
181              
182             Command line parameters may be passed to NetSDS application to override defaults.
183              
184             =over
185              
186             =item * B<--conf> - path to config file
187              
188             =item * B<--[no]debug> - set debug mode
189              
190             =item * B<--[no]daemon> - set daemon/foreground mode
191              
192             =item * B<--[no]verbose> - set verbosity mode
193              
194             =item * B<--name> - set application name
195              
196             =back
197              
198             These CLI options overrides C, C, C, C and C default parameters
199             that are passed in run() method.
200              
201             Examples:
202              
203             # Debugging in foreground mode
204             ./application --config=/etc/myapp.conf --nodaemon --debug
205              
206             # Set application name explicitly
207             ./application --name=myapp
208              
209             =cut
210              
211             package NetSDS::App;
212              
213 2     2   19392 use 5.8.0;
  2         8  
  2         99  
214 2     2   12 use strict;
  2         6  
  2         66  
215 2     2   11 use warnings;
  2         4  
  2         65  
216              
217 2     2   11 use base 'NetSDS::Class::Abstract';
  2         4  
  2         209  
218              
219             use version; our $VERSION = '1.301';
220              
221             use NetSDS::Logger; # API to syslog daemon
222             use NetSDS::Conf; # Configuration file processor
223             use NetSDS::EDR; # Module writing Event Detail Records
224              
225             use Proc::Daemon; # Daemonization
226             use Proc::PID::File; # Managing PID files
227             use Getopt::Long qw(:config auto_version auto_help pass_through);
228              
229             use POSIX;
230             use Carp;
231              
232             #===============================================================================
233             #
234              
235             =head1 CLASS API
236              
237             =over
238              
239             =item B - class constructor
240              
241             Constructor is usually invoked from C class method.
242             It creates application object and set its initial properties
243             from oarameters passed as hash.
244              
245             Standard parameters are:
246              
247             * name - application name
248             * debug - set to 1 for debugging
249             * daemon - set to 1 for daemonization
250             * verbose - set to 1 for more verbosity
251             * use_pidfile - set to 1 for PID files processing
252             * pid_dir - path to PID files catalog
253             * conf_file - path to configuration file
254             * has_conf - set to 1 if configuration file is necessary
255             * auto_features - set to 1 for auto features inclusion
256             * infinite - set to 1 for inifinite loop
257              
258             =cut
259              
260             #-----------------------------------------------------------------------
261             sub new {
262              
263             my ( $class, %params ) = @_;
264              
265             my $self = $class->SUPER::new(
266             name => undef, # application name
267             pid => $$, # proccess PID
268             debug => undef, # debug mode flag
269             daemon => undef, # daemonize if 1
270             verbose => undef, # be more verbose if 1
271             use_pidfile => undef, # check PID file if 1
272             pid_dir => '/var/run/NetSDS', # PID files catalog (default is /var/run/NetSDS)
273             conf_file => undef, # configuration file name
274             conf => undef, # configuration data
275             logger => undef, # logger object
276             has_conf => 1, # is configuration file necessary
277             auto_features => 0, # are automatic features allowed or not
278             infinite => 1, # is infinite loop
279             edr_file => undef, # path to EDR file
280             %params,
281             );
282              
283             return $self;
284              
285             } ## end sub new
286              
287             #***********************************************************************
288              
289             =item B - application launcher
290              
291             This method calls class constructor and then switch to C method.
292              
293             All method parameters are transparently passed to application constructor.
294              
295             #!/usr/bin/env perl
296            
297             use 5.8.0;
298             use warnings;
299             use strict;
300              
301             MyApp->run(
302             conf_file => '/etc/myapp.conf',
303             daemon => 1,
304             use_pidfile => 1,
305             );
306              
307             1;
308              
309             # **********************************
310             # Logic of application
311              
312             package MyApp;
313             use base 'NetSDS::App';
314             1;
315              
316             =cut
317              
318             #-----------------------------------------------------------------------
319             sub run {
320              
321             my $class = shift(@_);
322              
323             # Create application instance
324             if ( my $app = $class->new(@_) ) {
325              
326             # Framework initialization
327             $app->initialize();
328              
329             # Application workflow
330             $app->main_loop();
331              
332             # Framework finalization
333             $app->finalize();
334              
335             } else {
336              
337             carp "Can't start application";
338             return undef;
339              
340             }
341              
342             } ## end sub run
343              
344             #***********************************************************************
345              
346             =item B - application name
347              
348             This method is an accessor to application name allowing to retrieve
349             this or set new one.
350              
351             print "My name is " . $self->name;
352              
353             =cut
354              
355             #-----------------------------------------------------------------------
356              
357             __PACKAGE__->mk_accessors('name');
358              
359             #***********************************************************************
360              
361             =item B - PID of application process
362              
363             Read only access to process identifier (PID).
364              
365             print "My PID is " . $self->pid;
366              
367             =cut
368              
369             #-----------------------------------------------------------------------
370              
371             __PACKAGE__->mk_ro_accessors('pid');
372              
373             #***********************************************************************
374              
375             =item B - debugging flag
376              
377             This method provides an accessor to debugging flag.
378             If application called with --debug option it will return TRUE value.
379              
380             if ($self->debug) {
381             print "Debug info: " . $debug_data;
382             }
383              
384             =cut
385              
386             #-----------------------------------------------------------------------
387              
388             __PACKAGE__->mk_ro_accessors('debug');
389              
390             #***********************************************************************
391              
392             =item B - verbosity flag
393              
394             This method provides an accessor to verbosity flag.
395              
396             It may be used to increase application verbosity level if necessary.
397              
398             if ($self->verbose) {
399             print "I'm working!";
400             };
401              
402             NOTE: This flag is is for normal operations. If you need implement debug
403             output or other development/testing functionality - use debug() instead.
404              
405             =cut
406              
407             #-----------------------------------------------------------------------
408              
409             __PACKAGE__->mk_ro_accessors('verbose');
410              
411             #***********************************************************************
412              
413             =item B - accessor to logger
414              
415             This method is accessor to logger (object of L class).
416              
417             NOTE: There is no need to use this method directly in application. See C
418             method description to understand logging features.
419              
420             =cut
421              
422             #-----------------------------------------------------------------------
423             __PACKAGE__->mk_accessors('logger');
424              
425             #***********************************************************************
426              
427             =item B - accessor to configuration
428              
429             This method is accessor to application configuration represented as
430             hash reference returned by L module.
431              
432             Configuration sample:
433              
434             ------------------------
435             content_dir /var/lib/content
436              
437            
438             send_url http://127.0.0.1:13013/
439             login netsds
440             passwd topsecret
441            
442             ------------------------
443              
444             Code sample:
445              
446             # Retrieve configuration
447             my $content_dir = $self->conf->{content_dir};
448             my $kannel_url = $self->conf->{kannel}->{send_url};
449              
450             =cut
451              
452             #-----------------------------------------------------------------------
453             __PACKAGE__->mk_accessors('conf');
454              
455             #***********************************************************************
456              
457             =item B - PID file checking flag
458              
459             Paramters: TRUE if PID file checking required
460              
461             =cut
462              
463             #-----------------------------------------------------------------------
464              
465             __PACKAGE__->mk_accessors('use_pidfile');
466              
467             #***********************************************************************
468              
469             =item B - PID files storage
470              
471             Paramters: directory name
472              
473             $app->pid_dir("/var/run");
474              
475             =cut
476              
477             #-----------------------------------------------------------------------
478              
479             __PACKAGE__->mk_accessors('pid_dir');
480             #***********************************************************************
481              
482             =item B - daemonization flag
483              
484             Paramters: TRUE if application should be a daemon
485              
486             if ($self->daemon()) {
487             $self->log("info", "Yeah! I'm daemon!");
488             };
489              
490             =cut
491              
492             #-----------------------------------------------------------------------
493              
494             __PACKAGE__->mk_ro_accessors('daemon');
495              
496             #***********************************************************************
497              
498             =item B - auto features flag
499              
500             Automatic features inclusion allowed if TRUE.
501              
502             =cut
503              
504             #-----------------------------------------------------------------------
505              
506             __PACKAGE__->mk_ro_accessors('auto_features');
507              
508             #***********************************************************************
509              
510             =item B - is application in infinite loop
511              
512             Example:
513              
514             # Switch to infinite loop mode
515             $app->infinite(1);
516              
517             =cut
518              
519             #-----------------------------------------------------------------------
520              
521             __PACKAGE__->mk_accessors('infinite');
522              
523             #***********************************************************************
524              
525             #***********************************************************************
526              
527             =item B - accessor to EDR file name
528              
529             Paramters: EDR file path
530              
531             =cut
532              
533             #-----------------------------------------------------------------------
534              
535             __PACKAGE__->mk_accessors('edr_file');
536              
537             #***********************************************************************
538              
539             =item B
540              
541             Common application initialization:
542              
543             1. Reading config if necessary.
544              
545             2. Daemonize application.
546              
547             3. Check PID file for already running application instances.
548              
549             4. Start logger.
550              
551             5. Prepare default signal handlers.
552              
553             =cut
554              
555             #-----------------------------------------------------------------------
556             sub initialize {
557             my ( $self, %params ) = @_;
558              
559             $self->speak("Initializing application.");
560             # Determine application name from process name
561             if ( !$self->{name} ) {
562             $self->_determine_name();
563             }
564              
565             # Get CLI parameters
566             $self->_get_cli_param();
567              
568             # Daemonize, if needed
569             if ( $self->daemon() ) {
570             $self->speak("Daemonize, switch verbosity to false.");
571             $self->{verbose} = undef;
572             Proc::Daemon::Init;
573             }
574              
575             # Update PID if necessary
576             $self->{pid} = $$;
577              
578             # Create syslog handler
579             if ( !$self->logger ) {
580             $self->logger( NetSDS::Logger->new( name => $self->{name} ) );
581             $self->log( "info", "Logger started" );
582             }
583              
584             # Initialize EDR writer
585             if ( $self->edr_file ) {
586             $self->{edr_writer} = NetSDS::EDR->new( filename => $self->edr_file );
587             }
588              
589             # Process PID file if necessary
590             if ( $self->use_pidfile() ) {
591             if ( Proc::PID::File->running( dir => $self->pid_dir, name => $self->name ) ) {
592             $self->log( "error", "Application already running, stop immediately!" );
593             die "Application already running, stop immediately!";
594             }
595             }
596              
597             # Initialize configuration
598             if ( $self->{has_conf} ) {
599              
600             # Automatically determine configuration file name
601             if ( !$self->{conf_file} ) {
602             $self->{conf_file} = $self->config_file( $self->{name} . ".conf" );
603             }
604              
605             # Get configuration file
606             if ( my $conf = NetSDS::Conf->getconf( $self->{conf_file} ) ) {
607             $self->conf($conf);
608             $self->log( "info", "Configuration file read OK: " . $self->{conf_file} );
609             } else {
610             $self->log( "error", "Can't read configuration file: " . $self->{conf_file} );
611             }
612              
613             # Add automatic features
614             if ( $self->auto_features ) {
615             $self->use_auto_features();
616             }
617              
618             } ## end if ( $self->{has_conf})
619              
620             # Add signal handlers
621             $SIG{INT} = sub {
622             $self->speak("SIGINT caught");
623             $self->log( "warn", "SIGINT caught" );
624             $self->{to_finalize} = 1;
625             };
626              
627             $SIG{TERM} = sub {
628             $self->speak("SIGTERM caught");
629             $self->log( "warn", "SIGTERM caught" );
630             $self->{to_finalize} = 1;
631             };
632              
633             } ## end sub initialize
634              
635             #***********************************************************************
636              
637             =item B - add features to application
638              
639             This method implements automatic features inclusion by application
640             configuration file (see C sections).
641              
642             =cut
643              
644             #-----------------------------------------------------------------------
645              
646             sub use_auto_features {
647              
648             my ($self) = @_;
649              
650             if ( !$self->auto_features ) {
651             return $self->error("use_auto_features() called without setting auto_features property");
652             }
653              
654             # Check all sections in configuration
655             if ( $self->conf and $self->conf->{feature} ) {
656             my @features = ( keys %{ $self->conf->{feature} } );
657              
658             foreach my $f (@features) {
659             my $f_conf = $self->conf->{feature}->{$f};
660             my $class = $f_conf->{class};
661              
662             # Really add feature object
663             $self->add_feature( $f, $class, $f_conf );
664              
665             }
666             }
667              
668             } ## end sub use_auto_features
669              
670             #***********************************************************************
671              
672             =item B - add feature
673              
674             Paramters: feature name, class name, parameters (optional)
675              
676             Returns: feature object
677              
678             $self->add_feature('kannel','NetSDS::Feature::Kannel', $self->conf->{feature}->{kannel});
679             $self->kannel->send(.....);
680              
681             =cut
682              
683             #-----------------------------------------------------------------------
684              
685             sub add_feature {
686              
687             my $self = shift @_;
688             my $name = shift @_;
689             my $class = shift @_;
690             my $conf = shift @_;
691              
692             # Try to use necessary classes
693             eval "use $class";
694             if ($@) {
695             return $self->error( "Can't add feature module $class: " . $@ );
696             }
697              
698             # Feature class invocation
699             eval {
700             # Create feature instance
701             $self->{$name} = $class->create( $self, $conf, @_ );
702             # Add logger
703             $self->{$name}->{logger} = $self->logger;
704             };
705             if ($@) {
706             return $self->error( "Can't initialize feature module $class: " . $@ );
707             }
708              
709             # Create accessor to feature
710             $self->mk_accessors($name);
711              
712             # Send verbose output
713             $self->speak("Feature added: $name => $class");
714              
715             # Write log message
716             $self->log( "info", "Feature added: $name => $class" );
717              
718             } ## end sub add_feature
719              
720             #***********************************************************************
721              
722             =item B - switch to finalization stage
723              
724             This method called if we need to finish application.
725              
726             =cut
727              
728             #-----------------------------------------------------------------------
729             sub finalize {
730             my ( $self, $msg ) = @_;
731              
732             $self->log( 'info', 'Application stopped' );
733              
734             exit(0);
735             }
736              
737             #***********************************************************************
738              
739             =item B - user defined initialization hook
740              
741             Abstract method for postinitialization procedures execution.
742              
743             Arguments and return defined in inherited classes.
744             This method should be overwritten in exact application.
745              
746             Remember that start() methhod is invoked after initialize()
747              
748             =cut
749              
750             #-----------------------------------------------------------------------
751             sub start {
752              
753             my ( $self, %params ) = @_;
754              
755             return 1;
756             }
757              
758             #***********************************************************************
759              
760             =item B - main loop iteration hook
761              
762             Abstract method for main loop iteration procedures execution.
763              
764             Arguments and return defined in inherited classes.
765              
766             This method should be overwritten in exact application.
767              
768             =cut
769              
770             #-----------------------------------------------------------------------
771             sub process {
772              
773             my ( $self, %params ) = @_;
774              
775             return 1;
776             }
777              
778             #***********************************************************************
779              
780             =item B - post processing hook
781              
782             This method should be rewritten in target class to contain real
783             post processing routines.
784              
785             =cut
786              
787             #-----------------------------------------------------------------------
788             sub stop {
789             my ( $self, %params ) = @_;
790              
791             return 1;
792             }
793              
794             #***********************************************************************
795              
796             =item B - main loop algorithm
797              
798             This method provide default main loop alghorythm implementation and may
799             be rewritten for alternative logic.
800              
801             =back
802              
803             =cut
804              
805             #-----------------------------------------------------------------------
806             sub main_loop {
807             my ($self) = @_;
808              
809             # Run startup hooks
810             my $ret = $self->start();
811              
812             # Run processing hooks
813             while ( !$self->{to_finalize} ) {
814              
815             # Call production code
816             $ret = $self->process();
817              
818             # Process infinite loop
819             unless ( $self->{infinite} ) {
820             $self->{to_finalize} = 1;
821             }
822             }
823              
824             # Run finalize hooks
825             $ret = $self->stop();
826              
827             } ## end sub main_loop
828              
829             #***********************************************************************
830              
831             =head1 LOGGING AND ERROR HANDLING
832              
833             =over
834              
835             =item B - write message to log
836              
837             This method provides ablity to write log messages to syslog.
838              
839             Example:
840              
841             $self->log("info", "New message arrived with id=$msg_id");
842              
843             =cut
844              
845             #-----------------------------------------------------------------------
846             sub log {
847              
848             my ( $self, $level, $message ) = @_;
849              
850             # Try to use syslog handler
851             if ( $self->logger() ) {
852             $self->logger->log( $level, $message );
853             } else {
854             # No syslog, send error to STDERR
855             carp "[$level] $message";
856             }
857              
858             return undef;
859              
860             } ## sub log
861              
862             #***********************************************************************
863              
864             =item B - return error with logging
865              
866             This method extends inherited method functionality with automatically
867             logging this message to syslog.
868              
869             Example:
870              
871             if (!$dbh->ping) {
872             return $self->error("We have problem with DBMS");
873             }
874              
875             =cut
876              
877             #-----------------------------------------------------------------------
878              
879             sub error {
880             my ( $self, $message ) = @_;
881              
882             $self->log( "error", $message );
883             return $self->SUPER::error($message);
884              
885             }
886              
887             #***********************************************************************
888              
889             =item B - verbose output
890              
891             Paramters: list of strings to be written as verbose output
892              
893             This method implements verbose output to STDOUT.
894              
895             $self->speak("Do something");
896              
897             =cut
898              
899             #-----------------------------------------------------------------------
900              
901             sub speak {
902              
903             my ( $self, @params ) = @_;
904              
905             if ( $self->verbose ) {
906             print join( "", @params );
907             print "\n";
908             }
909             }
910              
911             #***********************************************************************
912              
913             =item B - write EDR
914              
915             Paramters: list of EDR records to write
916              
917             $app->edr({
918             event => "call",
919             status => "rejected",
920             });
921              
922             =cut
923              
924             #-----------------------------------------------------------------------
925              
926             sub edr {
927              
928             my ( $self, @records ) = @_;
929              
930             if ( $self->{edr_writer} ) {
931             return $self->{edr_writer}->write(@records);
932             } else {
933             return $self->error("Can't write EDR to undefined destination");
934             }
935              
936             }
937              
938             #-----------------------------------------------------------------------
939              
940             #***********************************************************************
941              
942             =item B - determine full configuration file name
943              
944             =cut
945              
946             #-----------------------------------------------------------------------
947              
948             sub config_file {
949              
950             my ( $self, $file_name ) = @_;
951              
952             my $conf_file;
953             if ( $file_name =~ /^\// ) {
954             $conf_file = $file_name;
955             } else {
956              
957             # Try to find path by NETSDS_CONF_DIR environment
958             my $file = ( $ENV{NETSDS_CONF_DIR} || "/etc/NetSDS/" );
959             $file =~ s/([^\/])$/$1\//;
960             $conf_file = $file . $file_name;
961              
962             # Last resort - local folder (use for debug, not production)
963             unless ( -f $conf_file && -r $conf_file ) {
964             $conf_file = "./" . $file_name;
965             }
966              
967             }
968              
969             return $conf_file;
970             } ## end sub config_file
971              
972             # Determine application name from script name
973             sub _determine_name {
974              
975             my ($self) = @_;
976              
977             # Dont override predefined name
978             if ( $self->{name} ) {
979             return $self->{name};
980             }
981              
982             $self->{name} = $0; # executable script
983             $self->{name} =~ s/^.*\///; # remove directory path
984             $self->{name} =~ s/\.(pl|cgi|fcgi)$//; # remove standard extensions
985              
986             }
987              
988             # Determine execution parameters from CLI
989             sub _get_cli_param {
990              
991             my ($self) = @_;
992              
993             my $conf = undef;
994             my $debug = undef;
995             my $daemon = undef;
996             my $verbose = undef;
997             my $name = undef;
998              
999             # Get command line arguments
1000             GetOptions(
1001             'conf=s' => \$conf,
1002             'debug!' => \$debug,
1003             'daemon!' => \$daemon,
1004             'verbose!' => \$verbose,
1005             'name=s' => \$name,
1006             );
1007              
1008             # Set configuration file name
1009             if ($conf) {
1010             $self->{conf_file} = $conf;
1011             }
1012              
1013             # Set debug mode
1014             if ( defined $debug ) {
1015             $self->{debug} = $debug;
1016             }
1017              
1018             # Set daemon mode
1019             if ( defined $daemon ) {
1020             $self->{daemon} = $daemon;
1021             }
1022              
1023             # Set verbose mode
1024             if ( defined $verbose ) {
1025             $self->{verbose} = $verbose;
1026             }
1027              
1028             # Set application name
1029             if ( defined $name ) {
1030             $self->{name} = $name;
1031             }
1032              
1033             } ## end sub _get_cli_param
1034              
1035             1;
1036              
1037             __END__