]> git.evergreen-ils.org Git - OpenSRF.git/blob - bin/osrf_ctl.sh.in
LP1204123 Improved per-service control (C/Perl)
[OpenSRF.git] / bin / osrf_ctl.sh.in
1 #!/bin/sh
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12  
13 # Strictness to avoid folly
14 set -e
15 set -u
16
17 prefix=@prefix@
18 exec_prefix=@exec_prefix@
19
20 OPT_ACTION=""
21 OPT_CONFIG=""
22 OPT_PID_DIR=""
23 OPT_SIGNAL=""
24 OPT_SERVICE=""
25 OSRF_HOSTNAME=""
26
27 # ---------------------------------------------------------------------------
28 # Make sure we're running as the correct user
29 # ---------------------------------------------------------------------------
30 [ $(whoami) != 'opensrf' ] && echo 'Must run as user "opensrf"' && exit;
31
32
33 usage() {
34         cat << EOF
35
36 usage: $0 [OPTION]... -c <c_config> -a <action>
37 usage: $0 -a signal -k <signal> -s <service>
38
39 Mandatory parameters:
40   -a    action to perform
41
42 Optional parameters:
43   -c    full path to C configuration file (opensrf_core.xml)
44   -d    store PID files in this directory
45   -l    accept 'localhost' as the fully-qualified domain name
46   -k    signal to send to process. Argument is passed directly to 'kill'.
47   -s    service name.  Used in conjunction with -k.
48
49
50 Actions include:
51     start_router
52     stop_router
53     restart_router
54     start_perl
55     stop_perl
56     restart_perl
57     start_python
58     stop_python
59     restart_python
60     start_c
61     stop_c
62     restart_c
63     start_osrf
64     stop_osrf
65     restart_osrf
66     stop_all
67     start_all
68     restart_all
69     smart_clear     - Clear all PID files that don't refer to a process 
70     clear_pid       - Clear all PID files
71     signal          - send signal specified by -k to service specified by -s
72     signal_all      - send signal specified by -k to all services
73
74
75 Examples:
76   $0 -a restart_all
77   $0 -l -c opensrf_core.xml -a restart_all
78   $0 -a signal -k opensrf.settings -s USR1
79   $0 -a signal_all -s HUP
80
81 EOF
82 }
83
84 # ---------------------------------------------------------------------------
85 # Load the command line options and set the global vars
86 # ---------------------------------------------------------------------------
87 while getopts  "a:d:c:s:k:lh" flag; do
88         case $flag in   
89                 "a")            OPT_ACTION="$OPTARG";;
90                 "c")            OPT_CONFIG="$OPTARG";;
91                 "d")            OPT_PID_DIR="$OPTARG";;
92                 "s")            OPT_SERVICE="$OPTARG";;
93                 "k")            OPT_SIGNAL="$OPTARG";;
94                 "l")            export OSRF_HOSTNAME="localhost";;
95                 "h"|*)  usage;;
96         esac;
97 done
98
99 OSRF_CONFIG="@bindir@/osrf_config"
100 [ ! -f "$OSRF_CONFIG" ] && OSRF_CONFIG=`which osrf_config`
101
102 [ -z "$OPT_CONFIG" ] && OPT_CONFIG=`$OSRF_CONFIG --sysconfdir`/opensrf_core.xml;
103 if [ ! -r "$OPT_CONFIG" ]; then
104         echo "Please specify the location of the opensrf_core.xml file using the -c flag";
105         exit 1;
106 fi;
107 [ -z "$OPT_PID_DIR" ] && OPT_PID_DIR=`$OSRF_CONFIG --localstatedir`/run/opensrf;
108 [ -z "$OPT_ACTION" ] && usage;
109
110 PID_ROUTER="$OPT_PID_DIR/router.pid";
111 PID_OSRF_PERL="$OPT_PID_DIR/osrf_perl.pid";
112 PID_OSRF_PYTHON="$OPT_PID_DIR/osrf_python.pid";
113 PID_OSRF_C="$OPT_PID_DIR/osrf_c.pid";
114
115 # apply some sanity checks to the signal handling arguments
116 if [ ${OPT_ACTION%_all} = "signal" ]; then
117     warning="";
118
119     [ -z "$OPT_SIGNAL" ] && \
120         warning="-a $OPT_ACTION requires a signal specified by -k";
121
122     [ $OPT_ACTION = "signal" -a -z "$OPT_SERVICE" ] && \
123         warning="$warning\n-a $OPT_ACTION requires a service specified by -s";
124
125     [ $OPT_ACTION = "signal_all" -a -n "$OPT_SERVICE" ] && \
126         warning="$warning\n-s $OPT_SERVICE cannot be used together with $OPT_ACTION";
127
128     if [ -n "$warning" ]; then
129         usage;
130         echo "------------"
131         echo -e $warning;
132         exit;
133     fi;
134
135     [ $OPT_ACTION = "signal_all" ] && OPT_SERVICE="*";
136 fi;
137
138 # ---------------------------------------------------------------------------
139 # Utility code for checking the PID files
140 # ---------------------------------------------------------------------------
141 do_action() {
142
143         action="$1"; 
144         pidfile="$2";
145         item="$3"; 
146
147         if [ $action = "start" ]; then
148
149                 if [ -e $pidfile ]; then
150                         pid=$(cat $pidfile);
151                         reported=$(ps ax | grep "$item" | grep -v grep | awk '{print $1}' | awk '{ printf "%s ", $0 }')
152                         
153                         if [ "$pid " = "$reported" ]; then
154                                 echo "$item already started : $pid";
155                                 return 0;
156                         else
157                                 echo "$item not started, but PID file exists, removing file and starting";
158                                 rm $pidfile;
159                                 return 0;
160                         fi;
161                 fi;
162                 echo "Starting $item";
163         fi;
164
165         if [ $action = "stop" ]; then
166
167                 if [ ! -e $pidfile ]; then
168                         echo "$item not running";
169                         return 0;
170                 fi;
171
172         while read pid; do
173             if [ -n "$pid" ]; then
174                 echo "Stopping $item process $pid..."
175                 kill -s INT $pid
176             fi;
177         done < $pidfile;
178                 rm -f $pidfile;
179
180         fi;
181
182         return 0;
183 }
184
185
186 # ---------------------------------------------------------------------------
187 # Start / Stop functions
188 # ---------------------------------------------------------------------------
189
190
191 start_router() {
192         do_action "start" $PID_ROUTER "OpenSRF Router";
193         opensrf_router $OPT_CONFIG routers
194     sleep 2; # give the router procs time to fork and appear in ps
195         pid=$(ps ax | grep "OpenSRF Router" | grep -v grep | awk '{print $1}')
196         echo $pid > $PID_ROUTER;
197         return 0;
198 }
199
200 stop_router() {
201         do_action "stop" $PID_ROUTER "OpenSRF Router";
202         return 0;
203 }
204
205 # The clean way to do this would be to invoke the "start_all" action
206 # on opensrf.py, but that seems to randomly fail for services. So we
207 # start each one separately from a bash script instead.
208 start_python() {
209     [ ! $($OSRF_CONFIG | grep OSRF_PYTHON) ] && return;
210     echo "Starting OpenSRF Python";
211     
212     if [ -e $PID_OSRF_PYTHON ]; then  #If python is started already (or it thinks so).
213     cat << EOF
214 Python processes are either already running, or were not correctly shut down.
215 Now clearing any stale PID files and restarting Perl processes.
216 EOF
217     rm $PID_OSRF_PYTHON;
218     smart_clear;
219     fi;
220
221     OPT_LOCAL=""
222     [ "$OSRF_HOSTNAME" = "localhost" ] && OPT_LOCAL="-l"
223     for service in `opensrf.py -a list_all $OPT_LOCAL`; do
224             opensrf.py -p $OPT_PID_DIR -f $OPT_CONFIG -d -a start -s $service $OPT_LOCAL
225             [ "$?" = "0" ] && echo "Python Started" > $PID_OSRF_PYTHON;  #Dummy pid file, removed when a proper shutdown happens.
226     done
227     return 0;
228 }
229
230 stop_python() {
231     [ ! $($OSRF_CONFIG | grep OSRF_PYTHON) ] && return;
232     echo "Stopping OpenSRF Python";
233     [ -e $PID_OSRF_PYTHON ] && rm $PID_OSRF_PYTHON;
234     OPT_LOCAL=""
235     [ "$OSRF_HOSTNAME" = "localhost" ] && OPT_LOCAL="-l"
236     set +e # Ignore errors for NXDOMAIN
237     opensrf.py -p $OPT_PID_DIR -f $OPT_CONFIG -a stop_all $OPT_LOCAL
238     set -e # Errors matter again
239     sleep 1;
240     return 0;
241 }
242
243 start_perl() {
244     echo "Starting OpenSRF Perl";
245     
246     if [ -e $PID_OSRF_PERL ]; then  #If perl is started already (or it thinks so)
247     cat << EOF
248 Perl processes are either already running, or were not correctly shut down.
249 Now clearing any stale PID files and restarting Perl processes.
250 EOF
251     rm $PID_OSRF_PERL;
252     smart_clear;
253     fi;
254
255     PL_ARGS="--verbose --pid-dir $OPT_PID_DIR --config $OPT_CONFIG --settings-startup-pause 3";
256
257     if [ -n "$OPT_SERVICE" ]; then 
258         PL_ARGS="$PL_ARGS --action start --service $OPT_SERVICE";
259     else
260         PL_ARGS="$PL_ARGS --action start_all";
261     fi;
262     
263     echo "opensrf-perl.pl $PL_ARGS";
264     opensrf-perl.pl $PL_ARGS;
265
266     #Dummy pid file, removed when a proper shutdown happens.
267     [ "$?" = "0" ] && echo "Perl Started" > $PID_OSRF_PERL;  
268         return 0;
269 }
270
271 stop_perl() {
272     echo "Stopping OpenSRF Perl";
273
274     PL_ARGS="--verbose --pid-dir $OPT_PID_DIR --config $OPT_CONFIG"
275
276     if [ -n "$OPT_SERVICE" ]; then 
277         PL_ARGS="$PL_ARGS --action stop --service $OPT_SERVICE";
278     else
279         PL_ARGS="$PL_ARGS --action stop_all";
280     fi;
281
282     echo "opensrf-perl.pl $PL_ARGS";
283     opensrf-perl.pl $PL_ARGS;
284
285     # remove the dummy PID file
286     [ -e $PID_OSRF_PERL ] && rm $PID_OSRF_PERL;
287         sleep 1;
288         return 0;
289 }
290
291 start_c() {
292     echo "Starting OpenSRF C";
293
294     if [ -e $PID_OSRF_C ]; then # If C is started already (or it thinks so)
295     cat << EOF
296 C processes are either already running, or were not correctly shut down.
297 Now clearing any stale PID files and starting C processes.
298 EOF
299     rm $PID_OSRF_C;
300     smart_clear;
301     fi;
302
303         host=$OSRF_HOSTNAME
304         if [ "_$host" = "_" ]; then
305                 host=$(perl -MNet::Domain=hostfqdn -e 'print hostfqdn()');
306         fi;
307
308     C_ARGS="-h $host -c $OPT_CONFIG -x opensrf -p $OPT_PID_DIR";
309     if [ -n "$OPT_SERVICE" ]; then
310         C_ARGS="$C_ARGS -s $OPT_SERVICE -a start";
311     else
312         C_ARGS="$C_ARGS -a start_all";
313     fi;
314
315     echo "opensrf-c $C_ARGS";
316         opensrf-c $C_ARGS;
317
318     #Dummy pid file, removed when a proper shutdown happens.
319     [ "$?" = "0" ] && echo "C Started" > $PID_OSRF_C;
320         return 0;
321 }
322
323 stop_c() {
324     echo "Stopping OpenSRF C";
325         host=$OSRF_HOSTNAME
326         if [ "_$host" = "_" ]; then
327                 host=$(perl -MNet::Domain=hostfqdn -e 'print hostfqdn()');
328         fi;
329
330     C_ARGS="-h $host -c $OPT_CONFIG -x opensrf -p $OPT_PID_DIR";
331     if [ -n "$OPT_SERVICE" ]; then
332         C_ARGS="$C_ARGS -s $OPT_SERVICE -a stop";
333     else
334         C_ARGS="$C_ARGS -a stop_all";
335     fi;
336
337     echo "opensrf-c $C_ARGS";
338         opensrf-c $C_ARGS;
339
340     [ -e $PID_OSRF_C ] && rm $PID_OSRF_C;
341         sleep 1;
342         return 0;
343 }
344
345 clear_pid() {
346         echo "Clearing PID files...";
347         cd $OPT_PID_DIR;
348         [ 0 -lt ls | wc -l ] && rm -v *.pid;
349         return 0;
350 }
351
352 smart_clear() {
353         echo "Smart clearing PID files...";
354         for line in $(find $OPT_PID_DIR -name *.pid -type f)
355         do
356         if [ $line = $PID_OSRF_PERL -o $line = $PID_OSRF_C \
357             -o $line = $PID_OSRF_PYTHON ]; then
358             continue;
359         fi;
360
361                 running="false";
362                 for p in $(cat $line)
363                 do
364                         [ 0 -lt $(ps ax | grep "$p" | grep -v grep | wc -l) ] && running="true";
365                 done
366                 
367                 if [ $running = "false" ]; then
368                         rm $line;
369                         echo "Removing stale PID file: $line";
370                 fi;
371         done
372         
373         return 0;
374 }
375
376 # send signal $OPT_SIGNAL to the Listener for service $OPT_SERVICE
377 # if $OPT_SERVICE = "*", signal all OpenSRF Listener services
378 send_signal() {
379     sig=$OPT_SIGNAL;
380     service=$OPT_SERVICE;
381
382     # openrsf C services do not write per-process PID files,
383     # so the simplest approach is to locate all listeners via ps/grep
384
385     found=0;
386     for svc in $(ps ax | grep "OpenSRF Listener" | grep -v grep | \
387         perl -e 'while(<>){s/.*\[(.*)\].*/$1/; print}' | sort | uniq); do
388
389         if [ "$service" = "*" -o "$service" = "$svc" ]; then
390
391             # grab the listener PIDs
392             for pid in $(ps ax | grep "OpenSRF Listener \[$svc\]" | \
393                     grep -v grep | cut -d' ' -f1); do
394                 found=1;
395                 echo "Sending signal '$sig' to $pid : $svc";
396                 kill -s $sig $pid;
397             done;
398         fi;
399     done;
400
401     if [ $found -eq 0 ]; then
402         if [ "$service" = "*" ]; then
403             echo "I have no services to signal!"
404         else
405             echo "No PID found for $service!"
406         fi;
407     fi;
408 }
409
410 # ---------------------------------------------------------------------------
411 # Do the requested action
412 # ---------------------------------------------------------------------------
413 case $OPT_ACTION in
414         "start_router") start_router;;
415         "stop_router") stop_router;;
416         "restart_router") stop_router; start_router;;
417         "start_perl") start_perl;;
418         "stop_perl") stop_perl;;
419         "restart_perl") stop_perl; start_perl;;
420         "start_python") start_python;;
421         "stop_python") stop_python;;
422         "restart_python") stop_python; start_python;;
423         "start_c") start_c;;
424         "stop_c") stop_c;;
425         "restart_c") stop_c; start_c;;
426         "start_osrf") start_perl; start_c; start_python;;
427         "stop_osrf") stop_python; stop_c; stop_perl;;
428         "restart_osrf") stop_python; stop_c; stop_perl; start_perl; start_c; start_python;;
429         "stop_all") stop_python; stop_c; stop_perl; stop_router;;
430         "start_all") start_router; start_perl; start_c; start_python;;
431         "restart_all") stop_python; stop_c; stop_perl; stop_router; start_router; start_perl; start_c; start_python;;
432         "clear_pid") clear_pid;;
433         "smart_clear") smart_clear;;
434         "signal") send_signal;;
435         "signal_all") send_signal;;
436         *) usage;;
437 esac;
438
439
440