my $opt_start_all = 0;
my $opt_stop_all = 0;
my $opt_restart_all = 0;
+my $opt_start_services = 0;
+my $opt_stop_services = 0;
+my $opt_restart_services = 0;
my $opt_force_clean_process = 0;
+my $opt_router_de_register = 0;
+my $opt_router_de_register_all = 0;
+my $opt_router_re_register = 0;
+my $opt_router_re_register_all = 0;
+my $opt_reload = 0;
+my $opt_reload_all = 0;
my $opt_quiet = 0;
+my $opt_diagnostic = 0;
+my $opt_ignore_orphans = 0;
my $sclient;
my @perl_services;
my @nonperl_services;
+my %max_children_map;
my $hostname = $ENV{OSRF_HOSTNAME} || hostfqdn();
GetOptions(
'start-all' => \$opt_start_all,
'stop-all' => \$opt_stop_all,
'restart' => \$opt_restart,
- 'restart-all' => \$opt_restart_all
+ 'restart-all' => \$opt_restart_all,
+ 'start-services' => \$opt_start_services,
+ 'stop-services' => \$opt_stop_services,
+ 'restart-services' => \$opt_restart_services,
+ 'router-de-register' => \$opt_router_de_register,
+ 'router-de-register-all' => \$opt_router_de_register_all,
+ 'router-re-register' => \$opt_router_re_register,
+ 'router-re-register-all' => \$opt_router_re_register_all,
+ 'reload' => \$opt_reload,
+ 'reload-all' => \$opt_reload_all,
+ 'diagnostic' => \$opt_diagnostic,
+ 'ignore-orphans' => \$opt_ignore_orphans
);
if ($opt_localhost) {
my $C_COMMAND = "opensrf-c -c $opt_config -x opensrf -p $opt_pid_dir -h $hostname";
my $PY_COMMAND = "opensrf.py -f $opt_config -p $opt_pid_dir ". ($opt_localhost ? '-l' : '');
+sub verify_services {
+ my $service = shift;
+ return 1 if $service and $service eq 'router';
+ my @services = (@perl_services, map {$_->{service}} @nonperl_services);
+ if (@services) {
+ return 1 unless $service;
+ return 1 if grep { $_ eq $service } @services;
+ msg("$service is not configured to run on $hostname");
+ } else {
+ msg("No services are configured to run on $hostname");
+ }
+ msg("Perhaps you meant to use --localhost?") unless $opt_localhost;
+ exit;
+}
+
sub do_signal_send {
my $service = shift;
my $signal = shift;
my $service = shift;
my $ps = ($service eq 'router') ?
- "ps ax | grep 'OpenSRF Router'" :
- "ps ax | grep 'OpenSRF Listener \\[$service\\]'";
+ "ps x | grep 'OpenSRF Router'" :
+ "ps x | grep 'OpenSRF Listener \\[$service\\]'";
$ps .= " | grep -v grep | sed 's/^\\s*//' | cut -d' ' -f1";
my @pids = `$ps`;
}
+sub do_diagnostic {
+ my $alive = do_init(1);
-sub do_start_router {
- `opensrf_router $opt_config routers`;
+ my @services = get_service_list_from_files(1);
+ my @conf_services;
+ if ($alive) {
+ @conf_services = (@perl_services,
+ map {$_->{service}} @nonperl_services);
+ push(@services, @conf_services);
+ }
+
+ my %services;
+ my $len = 0;
+ for my $svc (@services) {
+ $len = length($svc) if length($svc) > $len;
+ $services{$svc} = 1;
+ }
- sleep 2; # give the router time to fork
- my @pids = `ps -C opensrf_router -o pid=`;
- s/^\s*|\n//g for @pids;
+ for my $svc (sort keys %services) {
+ my @pf_pids = get_service_pids_from_file($svc);
+ my @ps_pids = get_service_pids_from_ps($svc);
+ my $svc_str = sprintf("%-${len}s ", $svc);
+ my %seen;
- my $pidfile = get_pid_file('router');
- open(PF, '>', $pidfile) or die "Cannot open $pidfile: $!\n";
- foreach (@pids) {
- chomp;
- msg("starting service pid=$_ router");
- print PF "$_\n";
+ unless(@ps_pids or @pf_pids) {
+ msg("$svc_str is not running");
+ next;
+ }
+
+ for my $pid (@ps_pids) {
+ $seen{$pid} = 1;
+
+ my $str = "$svc_str [$pid] ";
+ my $times = `ps -o etime=,cputime= $pid`;
+ $times =~ s/^\s+|\s+$//g;
+ my @times = split(/ /, $times);
+ $str .= sprintf("uptime=%-11s cputime=%-11s ", $times[0], $times[1]);
+
+ if ($svc eq 'router') {
+ msg($str);
+ } else {
+ my @drones = `pgrep -f "Drone \\[$svc\\]"`;
+ my $dcount = scalar(@drones);
+ my $dmax = $max_children_map{$svc};
+ if (defined($dmax) && $dmax > 0) {
+ $str .= "#drones=$dcount/$dmax ";
+ $str .= sprintf('%3d%%', (int(($dcount / $dmax) * 100)));
+ } else {
+ $str .= "#drones=$dcount";
+ }
+ msg($str);
+ msg("\tERR $svc has no running drones.") unless @drones;
+ }
+
+ msg("\tERR $svc [$pid] NOT configured for this host.")
+ unless grep {$_ eq $svc} @conf_services
+ or $svc eq 'router';
+
+ msg("\tERR $svc [$pid] NOT found in PID file.")
+ unless grep {$_ eq $pid} @pf_pids;
+ }
+
+ for my $pid (@pf_pids) {
+ next if $seen{$pid};
+ msg("\tERR $svc Has PID file entry [$pid], ".
+ "which matches no running $svc processes");
+ }
}
- close PF;
+}
+
+
+
+sub do_start_router {
+
+ my $pidfile = get_pid_file('router');
+ `opensrf_router $opt_config routers $pidfile`;
+
+ sleep 2; # give the router time to fork (probably not need now but w/e)
}
# stop a specific service
}
sub do_init {
+ my $fail_ok = shift;
+
OpenSRF::System->bootstrap_client(config_file => $opt_config);
- die "Unable to bootstrap client for requests\n"
- unless OpenSRF::Transport::PeerHandle->retrieve;
+
+ if (!OpenSRF::Transport::PeerHandle->retrieve) {
+ return 0 if $fail_ok;
+ die "Unable to bootstrap client for requests\n";
+ }
load_settings(); # load the settings config if we can
next;
}
my $lang = $sclient->config_value('apps', $app, 'language') || '';
+
+ $max_children_map{$app} = $sclient->config_value(
+ 'apps', $app, 'unix_config', 'max_children');
+
if ($lang =~ /perl/i) {
push(@perl_services, $app);
} else {
unlink $pidfile;
}
- } elsif (@ps_pids) { # orphan process
+ } elsif (@ps_pids and not $opt_ignore_orphans) { # orphan process
if ($opt_force_clean_process) {
msg("service $service pid=@ps_pids is running with no pidfile");
}
}
- msg("$service is not configured to run on $hostname");
- return 1;
+ # should not get here
+ return 0;
}
+
sub do_start_all {
- msg("starting all services for $hostname");
+ msg("starting router and services for $hostname");
do_start('router');
+ return do_start_services();
+}
+
+sub do_start_services {
+ msg("starting services for $hostname");
if(grep {$_ eq 'opensrf.settings'} @perl_services) {
do_start('opensrf.settings');
# start with the listeners, then drones, then routers
my @greps = (
- "ps ax | grep 'OpenSRF Listener' ",
- "ps ax | grep 'OpenSRF Drone' ",
- "ps ax | grep 'OpenSRF Router' "
+ "ps x | grep 'OpenSRF Listener' ",
+ "ps x | grep 'OpenSRF Drone' ",
+ "ps x | grep 'OpenSRF Router' "
);
$_ .= "| grep -v grep | sed 's/^\\s*//' | cut -d' ' -f1" for @greps;
}
}
-sub do_stop_all {
+sub do_stop_services {
my @signals = @_;
+ @signals = qw/TERM INT KILL/ unless @signals;
- msg("stopping all services for $hostname");
-
+ msg("stopping services for $hostname");
my @services = get_service_list_from_files();
- @signals = qw/TERM INT KILL/ unless @signals;
-
+
for my $signal (@signals) {
my @redo;
last unless @services;
}
+ return 1;
+}
+
+sub do_stop_all {
+ my @signals = @_;
+ @signals = qw/TERM INT KILL/ unless @signals;
+
+ do_stop_services(@signals);
+
# graceful shutdown requires the presence of the router, so stop the
# router last. See if it's running first to avoid unnecessary warnings.
do_stop('router', $signals[0]) if get_service_pids_from_file('router');
return 1 if $opt_no_daemon;
my $service = shift;
my $pid_file = get_pid_file($service);
- #exit if OpenSRF::Utils::safe_fork();
- return 0 if OpenSRF::Utils::safe_fork();
- msg("starting service pid=$$ $service");
+ my $pid = OpenSRF::Utils::safe_fork();
+ if ($pid) { # parent
+ msg("starting service pid=$pid $service");
+ return 0;
+ }
chdir('/');
setsid();
close STDIN;
--help
Print this help message
+ --diagnostic
+ Print information about running services
+
==== starting services =====
--start-all
--start
Start the service specified by --service
+ --start-services
+ Start all services but do not start any routers
+
--restart-all
Restart the router and all services
--restart
Restart the service specified by --service
+ --restart-services
+ Restart all services but do not restart any routers
+
--force-clean-process
When starting a service, if a service process is already running
but no pidfile exists, kill the service process before starting
- the new one.
+ the new one. This applies to routers too.
+
+ --ignore-orphans
+ When starting a service, if a service process is already running but
+ no pidfile exists, ignore the existing process and carry on starting
+ the new one (i.e., ignore orphans). This applies to routers too.
==== stopping services =====
If the requested service does not have a matching PID file, an
attempt to locate the PID via 'ps' will be made.
+ --stop-services
+ Stop all services but do not stop any routers. See also --stop-all.
+
--graceful-shutdown-all
Send TERM signal to all services + router
--signal-timeout
Seconds to wait for a process to die after sending a shutdown signal.
All signals except HUP, USR1, and USR2 are assumed to be shutdown signals.
-
+
+ ==== special signals ====
+
+ --router-de-register
+ --router-de-register-all
+ Sends a SIGUSR1 signal to the selected service(s), which causes each
+ service's listener process to send an "unregister" command to all
+ registered routers. The --all variant sends the signal to all
+ running listeners. The non-(--all) variant requires a --service.
+
+ --router-re-register
+ --router-re-register-all
+ Sends a SIGUSR2 signal to the selected service(s), which causes each
+ service's listener process to send a "register" command to all
+ configured routers. The --all variant sends the signal to all
+ running listeners. The non-(--all) variant requires a --service.
+
+ --reload
+ --reload-all
+ Sends a SIGHUP signal to the selected service(s). SIGHUP causes
+ each listener process to reload its opensrf_core.xml config file
+ and gracefully re-launch drone processes. The -all variant sends
+ the signal to all services. The non-(-all) variant requires a
+ --service.
HELP
exit;
}
-# starting services
-do_init() and do_start($opt_service) if $opt_start;
-do_init() and do_stop($opt_service) and do_start($opt_service) if $opt_restart;
-do_init() and do_start_all() if $opt_start_all;
-do_init() and do_stop_all() and do_start_all() if $opt_restart_all;
+# we do not verify services for stop/signal actions, since those may
+# legitimately be used against services not (or no longer) configured
+# to run on the selected host.
+do_init() and verify_services($opt_service) if
+ ($opt_start or
+ $opt_start_all or
+ $opt_start_services or
+ $opt_restart or
+ $opt_restart_all or
+ $opt_restart_services) and (
+ not defined $opt_service or $opt_service ne 'router'
+ );
+
+# starting services. do_init() handled above
+do_start($opt_service) if $opt_start;
+do_stop($opt_service) and do_start($opt_service) if $opt_restart;
+do_start_all() if $opt_start_all;
+do_start_services() if $opt_start_services;
+do_stop_all() and do_start_all() if $opt_restart_all;
+do_stop_services() and do_start_services() if $opt_restart_services;
# stopping services
do_stop($opt_service) if $opt_stop;
do_stop_all() if $opt_stop_all;
+do_stop_services() if $opt_stop_services;
do_stop($opt_service, 'TERM') if $opt_shutdown_graceful;
do_stop($opt_service, 'INT') if $opt_shutdown_fast;
do_stop($opt_service, 'KILL') if $opt_shutdown_immediate;
do_kill_with_fire() if $opt_kill_with_fire;
# signaling
-do_signal($opt_service, $opt_signal) if $opt_signal;
-do_signal_all($opt_signal) if $opt_signal_all;
+$opt_signal = 'USR1' if $opt_router_de_register or $opt_router_de_register_all;
+$opt_signal = 'USR2' if $opt_router_re_register or $opt_router_re_register_all;
+$opt_signal = 'HUP' if $opt_reload or $opt_reload_all;
+
+do_signal($opt_service, $opt_signal) if $opt_signal and $opt_service;
+do_signal_all($opt_signal) if
+ $opt_signal_all or
+ $opt_reload_all or
+ $opt_router_de_register_all or
+ $opt_router_re_register_all;
+
+# misc
+do_diagnostic() if $opt_diagnostic;
+
# show help if no action was requested
do_help() if $opt_help or not (
$opt_start or
$opt_start_all or
+ $opt_start_services or
$opt_stop or
$opt_stop_all or
+ $opt_stop_services or
$opt_restart or
$opt_restart_all or
+ $opt_restart_services or
$opt_signal or
$opt_signal_all or
$opt_shutdown_graceful or
$opt_shutdown_fast_all or
$opt_shutdown_immediate or
$opt_shutdown_immediate_all or
- $opt_kill_with_fire
+ $opt_kill_with_fire or
+ $opt_diagnostic
)