#!/usr/bin/perl
#===============================================================================
# called by init.d script to control HILIS4 fastcgiexternalserver
# need to run as root to get uid change on fastcgi socket
# need to set fastcgiexternalserver socket path in httpd.conf
# run as lims_fastcgi_<centre> [start|stop|restart|status] + 2nd arg optional
# for tmp pid file for use while main processes restarted; can multi-restart
# from bash script - see example scripts below
#===============================================================================
use strict;
use warnings;
use lib '/home/raj/perl5/lib/perl5';
use POSIX qw(strftime);
use FCGI::ProcManager;
use Daemon::Control;
use Data::Dumper;
use CGI::Fast();
use FCGI;
use FindBin qw($Bin); # load AFTER local::lib Carp or FindBin loads system
use lib "$Bin/../lib"; # Carp, causing fastcgi errors on Deb6
use LIMS::Dispatch;
# use User::pwent; # getpwnam() - done by Daemon::Control now
# APACHE_USER, CENTRE & NPROCS vars set in init.d:
my $CENTRE = $ENV{CENTRE} || die 'no CENTRE env var set'; # warn $CENTRE;
my $GROUP = $ENV{APACHE_GROUP} || die 'no APACHE_GROUP env var set'; # warn $GROUP;
my $USER = $ENV{APACHE_USER} || die 'no APACHE_USER env var set'; # warn $USER;
my $NPROCS = $ENV{NPROCESSES} || 2; # use 2 if not defined
#-------------------------------------------------------------------------------
my $run_dir = '/var/run/hilis4'; # location of pid file, socket, stderr
my $self = $0; # warn $self; # this script
# get uid of apache user using User::pwent::getpwnam: done by Daemon::Control now
# my $uid = getpwnam($USER)->uid; # warn Dumper $uid; exit;
#-------------------------------------------------------------------------------
# define pid, stderr & stdout:
my $stderr = my $stdout = $run_dir . '/stderr.out'; # combine
my $pid_file = sprintf '%s.pid', join '/', $run_dir, $CENTRE; # warn $pid_file;
my $now = strftime "%d-%b-%Y %H:%M:%S", localtime;
# $ARGV[0] is control command (start, stop, status, etc); if 2rd arg passed in
# @ARGV, assumes request for new temp pidfile -> same socket:
if ($ARGV[1]) { # warn $ARGV[1];
$NPROCS = 1; # only need 1 for temp process
$pid_file .= '~'; # creates new pid file for use while main processes restarted
} # warn Dumper [$pid_file, $NPROCS];
my %args = (
name => 'HILIS4_' . $CENTRE,
# lsb_start => '$syslog $remote_fs',
# lsb_stop => '$syslog',
lsb_sdesc => 'HILIS4 daemon',
lsb_desc => 'Controls the HILIS4 fastcgiexternalserver',
path => $self, # this script
program => \&hilis4, # $program - using sub {} now
program_args => [ ],
pid_file => $pid_file,
stderr_file => $stderr,
stdout_file => $stdout,
user => $USER,
group => $GROUP,
fork => 2,
);
Daemon::Control->new(\%args)->run;
#-------------------------------------------------------------------------------
sub hilis4 {
my $socket = FCGI::OpenSocket( "$run_dir/$CENTRE.socket", 2 ); # path, backlog
my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket );
# print to stdout (set in daemon control script):
printf "FastCGI daemon started (pid $$) for %s %s\n", uc $CENTRE, $now;
open STDIN, "+</dev/null" or die $!;
open STDOUT, ">&STDIN" or die $!;
open STDERR, ">&STDIN" or die $!;
my $proc_manager = FCGI::ProcManager->new({ n_processes => $NPROCS });
# create PID file, unless already created by other process (eg Daemon::Control):
if (! -e $pid_file) { # warn 'here';
$proc_manager->pm_write_pid_file($pid_file);
}
$proc_manager->pm_manage();
$CGI::Fast::Ext_Request = $request;
while ( my $query = CGI::Fast->new() ) {
# set active db to production - default is `test`:
$ENV{ROSEDB_DEVINIT} = "$Bin/../config/rosedb_devinit_prod.pl";
# set flag for LIMS::_set_cgisession_options & QueryLog:
$ENV{FAST_CGI} = 1;
# switch LIMS::RDBO $Rose::DB::Object::Debug on
$ENV{RDBO_DEBUG} = 1;
# set DBI trace:
# $ENV{DBI_TRACE} = "1=$Bin/../logs/trace.log";
$proc_manager->pm_pre_dispatch();
eval {
LIMS::Dispatch->dispatch(
args_to_new => { QUERY => $query },
default => '',
debug => 0,
);
};
my $err = $@;
if ($err) {
warn "$0 error: $err";
exit 0; # to free $dbh from stuck transaction and restart process(es)
}
$proc_manager->pm_post_dispatch();
}
FCGI::CloseSocket( $socket );
}
__END__
example init.d scripts:
================================================================================
#!/bin/bash
# second arg after start/stop is captured in lims_fastcgi by $@ var and by .fcgi
# as $ARGV[1] and acts as flag to create temp pid process
for ctr in leeds uclh
do
if test $1 && test $1 != $ctr
then
continue
fi
/etc/init.d/lims_fastcgi_$ctr start tmp
sleep 2
/etc/init.d/lims_fastcgi_$ctr restart
sleep 2
/etc/init.d/lims_fastcgi_$ctr stop tmp
done
================================================================================
#!/bin/sh
export CENTRE=leeds
export NPROCESSES=3
. /etc/init.d/lims_fastcgi
================================================================================
#!/bin/sh
export APACHE_USER=www-data
export APACHE_GROUP=www-data
SCRIPT_DIR=/home/raj/apps/HILIS4/script
SCRIPT=hilis4.fcgi
if [ -x $SCRIPT_DIR/$SCRIPT ];
then
cd $SCRIPT_DIR
/usr/bin/perl $SCRIPT_DIR/$SCRIPT $@
else
echo "Required program $SCRIPT_DIR/$SCRIPT not found!"
exit 1;
fi