#!/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_ [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, "+&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