]> git.evergreen-ils.org Git - OpenSRF.git/blob - bin/opensrf-perl.pl.in
LP#1286198: use --ignore-orphans rather than --are-there-no-prisons
[OpenSRF.git] / bin / opensrf-perl.pl.in
1 #!/usr/bin/perl
2 # ---------------------------------------------------------------
3 # Copyright (C) 2008-2013 Georgia Public Library Service
4 # Copyright (C) 2013 Equinox Software, Inc
5 # Bill Erickson <berick@esilibrary.com>
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 # ---------------------------------------------------------------
17 use strict; use warnings;
18 use Getopt::Long;
19 use Net::Domain qw/hostfqdn/;
20 use POSIX qw/setsid :sys_wait_h/;
21 use OpenSRF::Utils::Logger q/$logger/;
22 use OpenSRF::System;
23 use OpenSRF::Transport::PeerHandle;
24 use OpenSRF::Utils::SettingsClient;
25 use OpenSRF::Transport::Listener;
26 use OpenSRF::Utils;
27 use OpenSRF::Utils::Config;
28
29 my $opt_service = undef;
30 my $opt_config = "@CONF_DIR@/opensrf_core.xml";
31 my $opt_pid_dir = "@PID_DIR@/run/opensrf";
32 my $opt_no_daemon = 0;
33 my $opt_settings_pause = 0;
34 my $opt_localhost = 0;
35 my $opt_help = 0;
36 my $opt_shutdown_graceful = 0;
37 my $opt_shutdown_fast = 0;
38 my $opt_shutdown_immediate = 0;
39 my $opt_shutdown_graceful_all = 0;
40 my $opt_shutdown_fast_all = 0;
41 my $opt_shutdown_immediate_all = 0;
42 my $opt_kill_with_fire = 0;
43 my $opt_signal = ''; # signal name
44 my $opt_signal_all = 0;
45 my $opt_signal_timeout = 30;
46 my $opt_start = 0;
47 my $opt_stop = 0;
48 my $opt_restart = 0;
49 my $opt_start_all = 0;
50 my $opt_stop_all = 0;
51 my $opt_restart_all = 0;
52 my $opt_start_services = 0;
53 my $opt_stop_services = 0;
54 my $opt_restart_services = 0;
55 my $opt_force_clean_process = 0;
56 my $opt_router_de_register = 0;
57 my $opt_router_de_register_all = 0;
58 my $opt_router_re_register = 0;
59 my $opt_router_re_register_all = 0;
60 my $opt_reload = 0;
61 my $opt_reload_all = 0;
62 my $opt_quiet = 0;
63 my $opt_diagnostic = 0;
64 my $opt_ignore_orphans = 0;
65 my $sclient;
66 my @perl_services;
67 my @nonperl_services;
68 my $hostname = $ENV{OSRF_HOSTNAME} || hostfqdn();
69
70 GetOptions(
71     'service=s' => \$opt_service,
72     'config=s' => \$opt_config,
73     'pid-dir=s' => \$opt_pid_dir,
74     'no-daemon' => \$opt_no_daemon,
75     'settings-startup-pause=i' => \$opt_settings_pause,
76     'localhost' => \$opt_localhost,
77     'help' => \$opt_help,
78     'quiet' => \$opt_quiet,
79     'graceful-shutdown' => \$opt_shutdown_graceful,
80     'fast-shutdown' => \$opt_shutdown_fast,
81     'immediate-shutdown' => \$opt_shutdown_immediate,
82     'graceful-shutdown-all' => \$opt_shutdown_graceful_all,
83     'fast-shutdown-all' => \$opt_shutdown_fast_all,
84     'immediate-shutdown-all' => \$opt_shutdown_immediate_all,
85     'kill-with-fire' => \$opt_kill_with_fire,
86     'force-clean-process' => \$opt_force_clean_process,
87     'signal-timeout' => \$opt_signal_timeout,
88     'signal=s' => \$opt_signal,
89     'signal-all' => \$opt_signal_all,
90     'start' => \$opt_start,
91     'stop' => \$opt_stop,
92     'start-all' => \$opt_start_all,
93     'stop-all' => \$opt_stop_all,
94     'restart' => \$opt_restart,
95     'restart-all' => \$opt_restart_all,
96     'start-services' => \$opt_start_services,
97     'stop-services' => \$opt_stop_services,
98     'restart-services' => \$opt_restart_services,
99     'router-de-register' => \$opt_router_de_register,
100     'router-de-register-all' => \$opt_router_de_register_all,
101     'router-re-register' => \$opt_router_re_register,
102     'router-re-register-all' => \$opt_router_re_register_all,
103     'reload' => \$opt_reload,
104     'reload-all' => \$opt_reload_all,
105     'diagnostic' => \$opt_diagnostic,
106     'ignore-orphans' => \$opt_ignore_orphans
107 );
108
109 if ($opt_localhost) {
110     $hostname = 'localhost';
111     $ENV{OSRF_HOSTNAME} = $hostname;
112 }
113
114 my $C_COMMAND = "opensrf-c -c $opt_config -x opensrf -p $opt_pid_dir -h $hostname";
115 my $PY_COMMAND = "opensrf.py -f $opt_config -p $opt_pid_dir ". ($opt_localhost ? '-l' : '');
116
117 sub verify_services {
118     my $service = shift;
119     return 1 if $service and $service eq 'router';
120     my @services = (@perl_services, map {$_->{service}} @nonperl_services);
121     if (@services) {
122         return 1 unless $service;
123         return 1 if grep { $_ eq $service } @services;
124         msg("$service is not configured to run on $hostname");
125     } else {
126         msg("No services are configured to run on $hostname");
127     }
128     msg("Perhaps you meant to use --localhost?") unless $opt_localhost;
129     exit;
130 }
131
132 sub do_signal_send {
133     my $service = shift;
134     my $signal = shift;
135
136     my @pids = get_service_pids_from_file($service);
137
138     if (!@pids) {
139         # no PID files exist.  see if the service is running anyway
140
141         @pids = get_service_pids_from_ps($service);
142         if (!@pids) {
143             msg("cannot signal $service : no pid file or running process");
144             return 0;
145         }
146     }
147
148     for my $pid (@pids) {
149         if (kill($signal, $pid) == 0) { # no process was signaled.  
150             msg("cannot signal $service: process $pid is not running");
151             my $pidfile = get_pid_file($service);
152             unlink $pidfile if $pidfile;
153             next;
154         }
155
156         msg("sending $signal signal to pid=$pid $service");
157     }
158
159     return 1;
160 }
161
162 # returns 2 if a process should have gone away but did not
163 # in the case of multiple PIDs (e.g. router), return the 
164 # status of any failures, but not the successes.
165 sub do_signal_wait {
166     my $service = shift;
167     my @pids = get_service_pids_from_file($service);
168
169     my $stat = 1;
170     for my $pid (@pids) {
171
172         # to determine whether a process has died, we have to send
173         # a no-op signal to the PID and check the success of that signal
174         my $sig_count;
175         for my $i (1..$opt_signal_timeout) {
176             $sig_count = kill(0, $pid);
177             last unless $sig_count;
178             sleep(1);
179         }
180
181         if ($sig_count) {
182             msg("timed out waiting on $service pid=$pid to die");
183             $stat = 2;
184             next;
185         }
186
187         # cleanup successful. remove the PID file
188         my $pidfile = get_pid_file($service);
189         unlink $pidfile if $pidfile;
190     }
191
192     return $stat;
193 }
194
195 sub get_pid_file {
196     my $service = shift;
197     return "$opt_pid_dir/$service.pid";
198 }
199
200 # services usually only have 1 pid, but the router will have at least 2
201 sub get_service_pids_from_file {
202     my $service = shift;
203     my $pid_file = get_pid_file($service);
204     return () unless -e $pid_file;
205     my @pids = `cat $pid_file`;
206     s/^\s*|\n//g for @pids;
207     return @pids;
208 }
209
210 sub get_service_pids_from_ps {
211     my $service = shift;
212
213     my $ps = ($service eq 'router') ?
214         "ps ax | grep 'OpenSRF Router'" :
215         "ps ax | grep 'OpenSRF Listener \\[$service\\]'";
216
217     $ps .= " | grep -v grep |  sed 's/^\\s*//' | cut -d' ' -f1";
218     my @pids = `$ps`;
219     s/^\s*|\n//g for @pids;
220
221     return @pids;
222 }
223
224
225 sub do_diagnostic {
226     my $alive = do_init(1);
227
228     my @services = get_service_list_from_files(1);
229     my @conf_services;
230     if ($alive) {
231         @conf_services = (@perl_services, 
232             map {$_->{service}} @nonperl_services);
233         push(@services, @conf_services);
234     }
235     
236     my %services;
237     my $len = 0;
238     for my $svc (@services) {
239         $len = length($svc) if length($svc) > $len;
240         $services{$svc} = 1;
241     }
242
243     for my $svc (sort keys %services) {
244         my @pf_pids = get_service_pids_from_file($svc);
245         my @ps_pids = get_service_pids_from_ps($svc); 
246         my $svc_str = sprintf("%-${len}s ", $svc);
247         my %seen;
248
249         unless(@ps_pids or @pf_pids) {
250             msg("$svc_str is not running");
251             next;
252         }
253
254         for my $pid (@ps_pids) {
255             $seen{$pid} = 1;
256
257             my $str = "$svc_str [$pid] ";
258             my $times = `ps -o etime=,cputime= $pid`;
259             $times =~ s/^\s+|\s+$//g;
260             my @times = split(/ /, $times);
261             $str .= sprintf("uptime=%-11s cputime=%-11s ", $times[0], $times[1]);
262
263             if ($svc eq 'router') {
264                 msg($str);
265             } else {
266                 my @drones = `pgrep -f "Drone \\[$svc\\]"`;
267                 $str .= "#drones=".scalar(@drones);
268                 msg($str);
269                 msg("\tERR $svc has no running drones.") unless @drones;
270             }
271
272             msg("\tERR $svc [$pid] NOT configured for this host.")
273                 unless grep {$_ eq $svc} @conf_services 
274                 or $svc eq 'router';
275
276             msg("\tERR $svc [$pid] NOT found in PID file.")
277                 unless grep {$_ eq $pid} @pf_pids;
278         }
279
280         for my $pid (@pf_pids) {
281             next if $seen{$pid};
282             msg("\tERR $svc Has PID file entry [$pid], ".
283                 "which matches no running $svc processes");
284         }
285     }
286 }
287
288
289
290 sub do_start_router {
291
292     my $pidfile = get_pid_file('router');
293     `opensrf_router $opt_config routers $pidfile`;
294
295     sleep 2; # give the router time to fork (probably not need now but w/e)
296 }
297
298 # stop a specific service
299 sub do_stop {
300     my ($service, @signals) = @_;
301     @signals = qw/TERM INT KILL/ unless @signals;
302     for my $sig (@signals) {
303         last unless do_signal($service, $sig) == 2;
304     }
305     return 1;
306 }
307
308 sub do_init {
309     my $fail_ok = shift;
310
311     OpenSRF::System->bootstrap_client(config_file => $opt_config);
312
313     if (!OpenSRF::Transport::PeerHandle->retrieve) {
314         return 0 if $fail_ok;
315         die "Unable to bootstrap client for requests\n";
316     }
317
318     load_settings(); # load the settings config if we can
319
320     my $sclient = OpenSRF::Utils::SettingsClient->new;
321     my $apps = $sclient->config_value("activeapps", "appname");
322
323     # disconnect the top-level network handle
324     OpenSRF::Transport::PeerHandle->retrieve->disconnect;
325
326     if($apps) {
327         $apps = [$apps] unless ref $apps;
328         for my $app (@$apps) {
329             if (!$sclient->config_value('apps', $app)) {
330                 msg("Service '$app' is listed for this host, ".
331                     "but there is no configuration for it in $opt_config");
332                 next;
333             }
334             my $lang = $sclient->config_value('apps', $app, 'language') || '';
335             if ($lang =~ /perl/i) {
336                 push(@perl_services, $app);
337             } else {
338                 push(@nonperl_services, {service => $app, lang => $lang});
339             }
340         }
341     }
342     return 1;
343 }
344
345 # start a specific service
346 sub do_start {
347     my $service = shift;
348
349     my @pf_pids = get_service_pids_from_file($service);
350     my @ps_pids = get_service_pids_from_ps($service); 
351
352     if (@pf_pids) { # had pidfile
353
354         if (@ps_pids) {
355             msg("service $service already running : @ps_pids");
356             return;
357
358         } else { # stale pidfile
359
360             my $pidfile = get_pid_file($service);
361             msg("removing stale pid file $pidfile");
362             unlink $pidfile;
363         }
364
365     } elsif (@ps_pids and not $opt_ignore_orphans) { # orphan process
366
367         if ($opt_force_clean_process) {
368             msg("service $service pid=@ps_pids is running with no pidfile");
369             do_signal($service, 'KILL');
370         } else {
371             msg("service $service pid=@ps_pids is running with no pidfile! ".
372                 "use --force-clean-process to automatically kill orphan processes");
373             return;
374         }
375     }
376
377     return do_start_router() if $service eq 'router';
378
379     load_settings() if $service eq 'opensrf.settings';
380
381     if(grep { $_ eq $service } @perl_services) {
382         return unless do_daemon($service);
383         OpenSRF::System->run_service($service, $opt_pid_dir);
384
385     } else {
386         # note: we don't daemonize non-perl services, but instead
387         # assume the controller for other languages manages that.
388         my ($svc) = grep { $_->{service} eq $service } @nonperl_services;
389         if ($svc) {
390             if ($svc->{lang} =~ /c/i) {
391                 system("$C_COMMAND -a start -s $service");
392                 return;
393             } elsif ($svc->{lang} =~ /python/i) {
394                 system("$PY_COMMAND -a start -s $service");
395                 return;
396             }
397         }
398     }
399
400     # should not get here
401     return 0;
402 }
403
404
405 sub do_start_all {
406     msg("starting router and services for $hostname");
407     do_start('router');
408     return do_start_services();
409 }
410
411 sub do_start_services {
412     msg("starting services for $hostname");
413
414     if(grep {$_ eq 'opensrf.settings'} @perl_services) {
415         do_start('opensrf.settings');
416         # in batch mode, give opensrf.settings plenty of time to start 
417         # before any non-Perl services try to connect
418         sleep $opt_settings_pause if $opt_settings_pause;
419     }
420
421     # start Perl services
422     for my $service (@perl_services) {
423         do_start($service) unless $service eq 'opensrf.settings';
424     }
425
426     # start each non-perl service individually instead of using the native
427     # start-all command.  this allows us to test for existing pid files 
428     # and/or running processes on each service before starting.
429     # it also means each service has to connect-fetch_setting-disconnect
430     # from jabber, which makes startup slightly slower than native start-all
431     do_start($_->{service}) for @nonperl_services;
432
433     return 1;
434 }
435
436 # signal a single service
437 sub do_signal {
438     my $service = shift;
439     my $signal = shift;
440     return do_signal_all($signal, $service);
441 }
442
443 # returns the list of running services based on presence of PID files.
444 # the 'router' service is not included by deault, since it's 
445 # usually treated special.
446 sub get_service_list_from_files {
447     my $include_router = shift;
448     my @services = `ls $opt_pid_dir/*.pid 2> /dev/null`;
449     s/^\s*|\n//g for @services;
450     s|.*/(.*)\.pid$|$1| for @services;
451     return @services if $include_router;
452     return grep { $_ ne 'router' } @services;
453
454
455 sub do_signal_all {
456     my ($signal, @services) = @_;                                              
457     @services = get_service_list_from_files() unless @services;     
458
459     do_signal_send($_, $signal) for @services;
460
461     # if user passed a know non-shutdown signal, we're done.
462     return if $signal =~ /HUP|USR1|USR2/;
463
464     do_signal_wait($_) for @services;
465 }
466
467 # pull all opensrf listener and drone PIDs from 'ps', 
468 # kill them all, and remove all pid files
469 sub do_kill_with_fire {
470     msg("killing with fire");
471
472     my @pids = get_running_pids();
473     for (@pids) {
474         next unless $_ =~ /\d+/;
475         my $proc = `ps -p $_ -o cmd=`;
476         chomp $proc;
477         msg("killing with fire pid=$_ $proc");
478         kill('KILL', $_);
479     }
480
481     # remove all of the pid files
482     my @files = `ls $opt_pid_dir/*.pid 2> /dev/null`;
483     s/^\s*|\n//g for @files;
484     for (@files) {
485         msg("removing pid file $_");
486         unlink $_;
487     }
488 }
489
490 sub get_running_pids {
491     my @pids;
492
493     # start with the listeners, then drones, then routers
494     my @greps = (
495         "ps ax | grep 'OpenSRF Listener' ",
496         "ps ax | grep 'OpenSRF Drone' ",
497         "ps ax | grep 'OpenSRF Router' "
498     );
499
500     $_ .= "| grep -v grep |  sed 's/^\\s*//' | cut -d' ' -f1" for @greps;
501
502     for my $grep (@greps) {
503         my @spids = `$grep`;
504         s/^\s*|\n//g for @spids;
505         push (@pids, @spids);
506     }
507
508     return @pids;
509 }
510
511 sub clear_stale_pids {
512     my @pidfile_services = get_service_list_from_files(1);
513     my @running_pids = get_running_pids();
514     
515     for my $svc (@pidfile_services) {
516         my @pids = get_service_pids_from_file($svc);
517         for my $pid (@pids) {
518             next if grep { $_ eq $pid } @running_pids;
519             my $pidfile = get_pid_file($svc);
520             msg("removing stale pid file $pidfile");
521             unlink $pidfile;
522         }
523     }
524 }
525
526 sub do_stop_services {
527     my @signals = @_;
528     @signals = qw/TERM INT KILL/ unless @signals;
529
530     msg("stopping services for $hostname");
531     my @services = get_service_list_from_files();
532
533     for my $signal (@signals) {
534         my @redo;
535
536         # send the signal to all PIDs
537         do_signal_send($_, $signal) for @services;
538
539         # then wait for them to go away
540         for my $service (@services) {
541             push(@redo, $service) if do_signal_wait($service) == 2;
542         }
543
544         @services = @redo;
545         last unless @services;
546     }
547
548     return 1;
549 }
550
551 sub do_stop_all {
552     my @signals = @_;
553     @signals = qw/TERM INT KILL/ unless @signals;
554
555     do_stop_services(@signals);
556
557     # graceful shutdown requires the presence of the router, so stop the 
558     # router last.  See if it's running first to avoid unnecessary warnings.
559     do_stop('router', $signals[0]) if get_service_pids_from_file('router'); 
560
561     return 1;
562 }
563
564 # daemonize us.  return true if we're the child, false if parent
565 sub do_daemon {
566     return 1 if $opt_no_daemon;
567     my $service = shift;
568     my $pid_file = get_pid_file($service);
569     my $pid = OpenSRF::Utils::safe_fork();
570     if ($pid) { # parent
571         msg("starting service pid=$pid $service");
572         return 0;
573     }
574     chdir('/');
575     setsid();
576     close STDIN;
577     close STDOUT;
578     close STDERR;
579     open STDIN, '</dev/null';
580     open STDOUT, '>/dev/null';
581     open STDERR, '>/dev/null';
582     `echo $$ > $pid_file`;
583     return 1;
584 }
585
586 # parses the local settings file
587 sub load_settings {
588     my $conf = OpenSRF::Utils::Config->current;
589     my $cfile = $conf->bootstrap->settings_config;
590     return unless $cfile;
591     my $parser = OpenSRF::Utils::SettingsParser->new();
592     $parser->initialize( $cfile );
593     $OpenSRF::Utils::SettingsClient::host_config =
594         $parser->get_server_config($conf->env->hostname);
595 }
596
597 sub msg {
598     my $m = shift;
599     print "* $m\n" unless $opt_quiet;
600 }
601
602 sub do_help {
603     print <<HELP;
604
605     Usage: $0 --localhost --start-all
606
607     --config <file> [default: @CONF_DIR@/opensrf_core.xml]
608         OpenSRF configuration file 
609         
610     --pid-dir <dir> [default: @PID_DIR@/run/opensrf]
611         Directory where process-specific PID files are kept
612
613     --settings-startup-pause
614         How long to give the opensrf.settings server to start up when running 
615         in batch mode (start_all).  The purpose is to give plenty of time for
616         the settings server to be up and active before any non-Perl services
617         attempt to connect.
618
619     --localhost
620         Force the hostname to be 'localhost', instead of the fully qualified
621         domain name for the machine.
622
623     --service <service>
624         Specifies which OpenSRF service to control
625
626     --quiet
627         Do not print informational messages to STDOUT 
628
629     --no-daemon
630         Do not detach and run as a daemon process.  Useful for debugging.  
631         Only works for Perl services and only when starting a single service.
632
633     --help
634         Print this help message
635
636     --diagnostic
637         Print information about running services
638
639     ==== starting services =====
640
641     --start-all
642         Start the router and all services
643
644     --start
645         Start the service specified by --service
646
647     --start-services
648         Start all services but do not start any routers
649
650     --restart-all
651         Restart the router and all services
652
653     --restart
654         Restart the service specified by --service
655
656     --restart-services
657         Restart all services but do not restart any routers
658
659     --force-clean-process
660         When starting a service, if a service process is already running 
661         but no pidfile exists, kill the service process before starting
662         the new one. This applies to routers too.
663
664     --ignore-orphans
665         When starting a service, if a service process is already running but
666         no pidfile exists, ignore the existing process and carry on starting
667         the new one (i.e., ignore orphans).  This applies to routers too.
668
669     ==== stopping services =====
670
671     --stop-all
672         Stop the router and all services.  Services are sent the TERM signal,
673         followed by the INT signal, followed by the KILL signal.  With each
674         iteration, the script pauses up to --signal-timeout seconds waiting
675         for each process to die before sending the next signal.
676
677     --stop
678         Stop the service specified by --service.  See also --stop-all.
679         If the requested service does not have a matching PID file, an
680         attempt to locate the PID via 'ps' will be made.
681
682     --stop-services
683         Stop all services but do not stop any routers.  See also --stop-all.
684
685     --graceful-shutdown-all
686         Send TERM signal to all services + router
687
688     --graceful-shutdown
689         Send TERM signal to the service specified by --service
690
691     --fast-shutdown-all
692         Send INT signal to all services + router
693
694     --fast-shutdown
695         Send INT signal to the service specified by --service
696
697     --immediate-shutdown-all
698         Send KILL signal to all services + router
699
700     --immediate-shutdown
701         Send KILL signal to the service specified by --service
702
703     --kill-with-fire
704         Send KILL signal to all running services + routers, regardless of 
705         the presence of a PID file, and remove all PID files indiscriminately.  
706
707     ==== signaling services =====
708
709     --signal-all
710         Send signal to all services
711
712     --signal
713         Name of signal to send.  If --signal-all is not specified, the 
714         signal will be sent to the service specified by --service.
715
716     --signal-timeout
717         Seconds to wait for a process to die after sending a shutdown signal.
718         All signals except HUP, USR1, and USR2 are assumed to be shutdown signals.
719
720     ==== special signals ====
721
722     --router-de-register
723     --router-de-register-all
724         Sends a SIGUSR1 signal to the selected service(s), which causes each 
725         service's listener process to send an "unregister" command to all 
726         registered routers.  The --all variant sends the signal to all 
727         running listeners.  The non-(--all) variant requires a --service.
728
729     --router-re-register
730     --router-re-register-all
731         Sends a SIGUSR2 signal to the selected service(s), which causes each 
732         service's listener process to send a "register" command to all 
733         configured routers.  The --all variant sends the signal to all
734         running listeners.  The non-(--all) variant requires a --service.
735
736     --reload
737     --reload-all
738         Sends a SIGHUP signal to the selected service(s).  SIGHUP causes
739         each listener process to reload its opensrf_core.xml config file 
740         and gracefully re-launch drone processes.  The -all variant sends
741         the signal to all services.  The non-(-all) variant requires a
742         --service.
743 HELP
744 exit;
745 }
746
747 # we do not verify services for stop/signal actions, since those may
748 # legitimately be used against services not (or no longer) configured
749 # to run on the selected host.
750 do_init() and verify_services($opt_service) if
751     ($opt_start or
752     $opt_start_all or
753     $opt_start_services or
754     $opt_restart or
755     $opt_restart_all or
756     $opt_restart_services) and (
757         not defined $opt_service or $opt_service ne 'router'
758     );
759
760 # starting services.  do_init() handled above
761 do_start($opt_service) if $opt_start;
762 do_stop($opt_service) and do_start($opt_service) if $opt_restart;
763 do_start_all() if $opt_start_all;
764 do_start_services() if $opt_start_services;
765 do_stop_all() and do_start_all() if $opt_restart_all;
766 do_stop_services() and do_start_services() if $opt_restart_services;
767
768 # stopping services
769 do_stop($opt_service) if $opt_stop;
770 do_stop_all() if $opt_stop_all;
771 do_stop_services() if $opt_stop_services;
772 do_stop($opt_service, 'TERM') if $opt_shutdown_graceful;
773 do_stop($opt_service, 'INT') if $opt_shutdown_fast;
774 do_stop($opt_service, 'KILL') if $opt_shutdown_immediate;
775 do_stop_all('TERM') if $opt_shutdown_graceful_all;
776 do_stop_all('INT') if $opt_shutdown_fast_all;
777 do_stop_all('KILL') if $opt_shutdown_immediate_all;
778 do_kill_with_fire() if $opt_kill_with_fire;
779
780 # signaling
781 $opt_signal = 'USR1' if $opt_router_de_register or $opt_router_de_register_all;
782 $opt_signal = 'USR2' if $opt_router_re_register or $opt_router_re_register_all;
783 $opt_signal = 'HUP'  if $opt_reload or $opt_reload_all;
784
785 do_signal($opt_service, $opt_signal) if $opt_signal and $opt_service;
786 do_signal_all($opt_signal) if 
787     $opt_signal_all or 
788     $opt_reload_all or
789     $opt_router_de_register_all or 
790     $opt_router_re_register_all;
791
792 # misc
793 do_diagnostic() if $opt_diagnostic;
794
795
796 # show help if no action was requested
797 do_help() if $opt_help or not (
798     $opt_start or 
799     $opt_start_all or 
800     $opt_start_services or 
801     $opt_stop or 
802     $opt_stop_all or 
803     $opt_stop_services or 
804     $opt_restart or 
805     $opt_restart_all or 
806     $opt_restart_services or 
807     $opt_signal or 
808     $opt_signal_all or
809     $opt_shutdown_graceful or
810     $opt_shutdown_graceful_all or
811     $opt_shutdown_fast or
812     $opt_shutdown_fast_all or
813     $opt_shutdown_immediate or
814     $opt_shutdown_immediate_all or
815     $opt_kill_with_fire or
816     $opt_diagnostic
817 )