f120e3152e53b5284da2baf5096c0d4388a87878
[OpenSRF.git] / bin / opensrf-perl.pl
1 #!/usr/bin/perl
2 # ---------------------------------------------------------------
3 # Copyright (C) 2008  Georgia Public Library Service
4 # Bill Erickson <erickson@esilibrary.com>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 # ---------------------------------------------------------------
16 use strict; use warnings;
17 use Getopt::Long;
18 use Net::Domain qw/hostfqdn/;
19 use POSIX qw/setsid :sys_wait_h/;
20 use OpenSRF::Utils::Logger q/$logger/;
21 use OpenSRF::System;
22 use OpenSRF::Transport::PeerHandle;
23 use OpenSRF::Utils::SettingsClient;
24 use OpenSRF::Transport::Listener;
25 use OpenSRF::Utils;
26 use OpenSRF::Utils::Config;
27
28 my $opt_action = undef;
29 my $opt_service = undef;
30 my $opt_config = undef;
31 my $opt_pid_dir = '/tmp';
32 my $opt_no_daemon = 0;
33 my $opt_help = 0;
34 my $sclient;
35 my $hostname = hostfqdn();
36 my @hosted_services;
37
38 GetOptions(
39     'action=s' => \$opt_action,
40     'service=s' => \$opt_service,
41     'config=s' => \$opt_config,
42     'pid-dir=s' => \$opt_pid_dir,
43     'no-daemon' => \$opt_no_daemon,
44     'help' => \$opt_help,
45 );
46
47
48 sub haltme {
49     kill('INT', -$$); #kill all in process group
50     exit;
51 };
52 $SIG{INT} = \&haltme;
53 $SIG{TERM} = \&haltme;
54
55 sub get_pid_file {
56     my $service = shift;
57     return "$opt_pid_dir/$service.pid";
58 }
59
60 # stop a specific service
61 sub do_stop {
62     my $service = shift;
63     my $pid_file = get_pid_file($service);
64     if(-e $pid_file) {
65         my $pid = `cat $pid_file`;
66         kill('INT', $pid);
67         waitpid($pid, 0);
68         unlink $pid_file;
69     } else {
70         msg("$service not running");
71     }
72     return 1;
73 }
74
75 sub do_init {
76     OpenSRF::System->bootstrap_client(config_file => $opt_config);
77     die "Unable to bootstrap client for requests\n"
78         unless OpenSRF::Transport::PeerHandle->retrieve;
79
80     load_settings(); # load the settings config if we can
81
82     my $sclient = OpenSRF::Utils::SettingsClient->new;
83     my $apps = $sclient->config_value("activeapps", "appname");
84
85     # disconnect the top-level network handle
86     OpenSRF::Transport::PeerHandle->retrieve->disconnect;
87
88     if($apps) {
89         $apps = [$apps] unless ref $apps;
90         for my $app (@$apps) {
91             push(@hosted_services, $app) 
92                 if $sclient->config_value('apps', $app, 'language') =~ /perl/i;
93         }
94     }
95     return 1;
96 }
97
98 # start a specific service
99 sub do_start {
100     my $service = shift;
101     load_settings() if $service eq 'opensrf.settings';
102
103     my $sclient = OpenSRF::Utils::SettingsClient->new;
104     my $apps = $sclient->config_value("activeapps", "appname");
105     OpenSRF::Transport::PeerHandle->retrieve->disconnect;
106
107     if(grep { $_ eq $service } @hosted_services) {
108         return unless do_daemon($service);
109         launch_net_server($service);
110         launch_listener($service);
111         $0 = "OpenSRF controller [$service]";
112         while(my $pid = waitpid(-1, 0)) {
113             $logger->debug("Cleaning up Perl $service process $pid");
114         }
115     }
116
117     msg("$service is not configured to run on $hostname");
118     return 1;
119 }
120
121 sub do_start_all {
122     do_start('opensrf.settings') if grep {$_ eq 'opensrf.settings'} @hosted_services;
123     for my $service (@hosted_services) {
124         do_start($service) unless $service eq 'opensrf.settings';
125     }
126     return 1;
127 }
128
129 sub do_stop_all {
130     do_stop($_) for @hosted_services;
131     return 1;
132 }
133
134 # daemonize us.  return true if we're the child, false if parent
135 sub do_daemon {
136     return 1 if $opt_no_daemon;
137     my $service = shift;
138     my $pid_file = get_pid_file($service);
139     #exit if OpenSRF::Utils::safe_fork();
140     return 0 if OpenSRF::Utils::safe_fork();
141     chdir('/');
142     setsid();
143     close STDIN;
144     close STDOUT;
145     close STDERR;
146     `echo $$ > $pid_file`;
147     return 1;
148 }
149
150 # parses the local settings file
151 sub load_settings {
152     my $conf = OpenSRF::Utils::Config->current;
153     my $cfile = $conf->bootstrap->settings_config;
154     return unless $cfile;
155     my $parser = OpenSRF::Utils::SettingsParser->new();
156     $parser->initialize( $cfile );
157     $OpenSRF::Utils::SettingsClient::host_config =
158         $parser->get_server_config($conf->env->hostname);
159 }
160
161 # starts up the unix::server master process
162 sub launch_net_server {
163     my $service = shift;
164     push @OpenSRF::UnixServer::ISA, 'Net::Server::PreFork';
165     unless(OpenSRF::Utils::safe_fork()) {
166         $0 = "OpenSRF Drone [$service]";
167         OpenSRF::UnixServer->new($service)->serve;
168         exit;
169     }
170     return 1;
171 }
172
173 # starts up the inbound listener process
174 sub launch_listener {
175     my $service = shift;
176     unless(OpenSRF::Utils::safe_fork()) {
177         $0 = "OpenSRF listener [$service]";
178         OpenSRF::Transport::Listener->new($service)->initialize->listen;
179         exit;
180     }
181     return 1;
182 }
183
184 sub msg {
185     my $m = shift;
186     print "* $m\n";
187 }
188
189 sub do_help {
190     print <<HELP;
191
192     Usage: perl $0 --pid_dir /var/run/opensrf --config /etc/opensrf/opensrf_core.xml --service opensrf.settings --action start
193
194     --action <action>
195         Actions include start, stop, restart, and start_all, stop_all, and restart_all
196
197     --service <service>
198         Specifies which OpenSRF service to control
199
200     --config <file>
201         OpenSRF configuration file 
202         
203     --pid-dir <dir>
204         Directory where process-specific PID files are kept
205         
206     --no-daemon
207         Do not detach and run as a daemon process.  Useful for debugging.
208         
209     --help
210         Print this help message
211 HELP
212 exit;
213 }
214
215
216 do_help() if $opt_help or not $opt_action;
217 do_init() and do_start($opt_service) if $opt_action eq 'start';
218 do_stop($opt_service) if $opt_action eq 'stop';
219 do_init() and do_stop($opt_service) and do_start($opt_service) if $opt_action eq 'restart';
220 do_init() and do_start_all() if $opt_action eq 'start_all';
221 do_init() and do_stop_all() if $opt_action eq 'stop_all';
222 do_init() and do_stop_all() and do_start_all() if $opt_action eq 'restart_all';
223
224