- 论坛徽章:
- 1
|
rc.conf:
perl_fcgi_enable="YES"
perl_fcgi_pidfile="/var/run/perl-fcgi.pid"
perl_fcgi_user="www"
perl_fcgi_group="www"
perl_fcgi_chdir="/"
perl_fcgi_chroot=""
perl_fcgi_socket="/tmp/perl-fcgi.sock"
perl_fcgi_socketbacklog="100"
perl_fcgi_socketmode="0777"
perl_fcgi_children="2"
perl_fcgi_childrentimeout="10"
perl_fcgi_max_requests="10000"
perl_fcgi_path_env="/bin:/usr/bin"
/usr/local/etc/rc.d/perl-fcgi- #!/bin/sh
- ### Rozhuk Ivan 2009.05
- ### startup script file for perl-fcgi
- ###
- # PROVIDE: perl_fcgi
- # REQUIRE: DAEMON
- # BEFORE: LOGIN
- # KEYWORD: shutdown
- . /etc/rc.subr
- name="perl_fcgi"
- rcvar=`set_rcvar`
- load_rc_config $name
- : ${perl_fcgi_enable="NO"}
- : ${perl_fcgi_pidfile="/var/run/perl-fcgi.pid"}
- : ${perl_fcgi_user="www"}
- : ${perl_fcgi_group="www"}
- : ${perl_fcgi_chdir=""}
- : ${perl_fcgi_chroot=""}
- : ${perl_fcgi_socket="127.0.0.1:9001"}
- : ${perl_fcgi_socketbacklog="10"}
- : ${perl_fcgi_socketmode="0777"}
- : ${perl_fcgi_children="5"}
- : ${perl_fcgi_childrentimeout="30"}
- : ${perl_fcgi_max_requests="1000"}
- : ${perl_fcgi_path_env="/bin:/usr/bin"}
- command="/usr/local/etc/perl-fcgi.pl"
- command_args="-d ${perl_fcgi_chdir} -s ${perl_fcgi_socket} -sb ${perl_fcgi_socket} -M ${perl_fcgi_socketmode} -F ${perl_fcgi_children} -Ft ${perl_fcgi_childrentimeout} -Fm ${perl_fcgi_max_requests} -P ${perl_fcgi_pidfile} -e ${perl_fcgi_path_env}"
- procname="perl-fcgi-pm"
- pidfile="${perl_fcgi_chroot}${perl_fcgi_pidfile}"
- required_dirs=${perl_fcgi_chroot}
- start_precmd="${name}_start_precmd"
- stop_postcmd="${name}_stop_postcmd"
- perl_fcgi_start_precmd()
- {
- touch ${perl_fcgi_chroot}${pidfile}
- chown ${perl_fcgi_user}:${perl_fcgi_group} ${perl_fcgi_chroot}${pidfile}
- }
- perl_fcgi_stop_postcmd()
- {
- rm -f ${pidfile}
- }
- run_rc_command "$1"
复制代码 创建perl-fcgi.pl 到/usr/local/etc/ 下- #!/usr/bin/perl -w
- ### Rozhuk Ivan, 2009
- ### fast cgi for perl scripts
- ### mod version 1.2
- ### origin: http://wiki.nginx.org//NginxSimpleCGI
- ### mod by Denis S. Filimonov (Guest) on 13.03.2008 18:37 http://www.ruby-forum.com/attachment/1583/fastcgi-wrapper.pl
- ### mod by mark: http://www.linux.org.ru/view-message.jsp?msgid=3532327
- ### final: http://wiki.nginx.org//NginxSimpleCGI
- ### additional: http://www.opennet.ru/base/dev/fastcgi_perl.txt.html
- use strict;
- use warnings;
- use FCGI; # /usr/ports/www/p5-FastCGI
- use FCGI::ProcManager qw(pm_manage pm_pre_dispatch pm_post_dispatch); # /usr/ports/www/p5-FCGI-ProcManager
- use Socket;
- use POSIX qw(setsid setuid);
- use Getopt::Long;
- require 'sys/syscall.ph';
- # settings
- my ($CURRENT_DIR,$SOCKET_ADDRESS,$SOCKET_BACKLOG,$SOCKET_MODE,$CHILDRENS_COUNT,$CHILDRENS_TIMEOUT,$CHILDRENS_MAX_REQ,$PIDFILE,$PATHENV);
- # global variables
- &startpoint();
- #this keeps the program alive or something after exec'ing perl scripts
- END() { }
- BEGIN() { }
- {no warnings; *CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; };
- eval q{exit};
- if ($@) { exit unless $@ =~ /^fakeexit/; };
- sub startpoint()
- {
- if ($#ARGV!=-1)
- {
- $CURRENT_DIR ='/';
- #$SOCKET_ADDRESS ='';
- $SOCKET_BACKLOG =10;
- $SOCKET_MODE =0777;
- $CHILDRENS_COUNT =2;
- $CHILDRENS_TIMEOUT =30;
- $CHILDRENS_MAX_REQ =100;
- #$PIDFILE ='';
- #$PATHENV ='/bin:/usr/bin';
- GetOptions( 'd:s' => \$CURRENT_DIR,
- 's=s' => \$SOCKET_ADDRESS,
- 'sb:i' => \$SOCKET_BACKLOG,
- 'M:i' => \$SOCKET_MODE,
- 'F:i' => \$CHILDRENS_COUNT,
- 'Ft:i' => \$CHILDRENS_TIMEOUT,
- 'Fm:i' => \$CHILDRENS_MAX_REQ,
- 'P:s' => \$PIDFILE,
- 'e:s' => \$PATHENV,
- );
- if (!defined($SOCKET_ADDRESS)) {usage();}
- # untainte input
- if ($SOCKET_ADDRESS =~ /^(.*)$/) {$SOCKET_ADDRESS = $1;}
- if (defined($PIDFILE)) {if ($PIDFILE =~ /^(.*)$/) {$PIDFILE = $1;}}
- if (defined($PATHENV))
- {
- if ($PIDFILE =~ /^(.*)$/) {$PIDFILE = $1;}
- }else{
- $PATHENV='/bin:/usr/bin';
- }
- #print "SOCKET_ADDRESS: $SOCKET_ADDRESS SOCKET_BACKLOG: $SOCKET_BACKLOG CHILDRENS_COUNT: $CHILDRENS_COUNT CHILDRENS_TIMEOUT: $CHILDRENS_TIMEOUT PIDFILE: $PIDFILE\n";
- daemonize();
- }else{
- usage();
- }
- }
- sub usage
- {
- print "Usage: perl-fcgi [options]\n\n";
- print " -d <directory> chdir to directory before spawning (default /)\n";
- print " -s <address/path> unix socket or tcp address:port\n";
- print " -sb <size> socket backlog size (default 10)\n";
- print " -M <mode> change Unix domain socket mode (default 0777)\n";
- print " -F <children> number of children to fork (default 2)\n";
- print " -Ft <timeout> children process timeout (default 30)\n";
- print " -Fm <num> children process max requests (default 100)\n";
- print " -P <path> name of PID-file for spawned process\n";
- print " -e <path> set new PATH environment (default /bin:/usr/bin)\n";
- #print "(root only)\n";
- #print " -c <directory> chroot to directory (default /)\n";
- #print " -S create socket before chroot() (default is to create the socket in the chroot)\n";
- #print " -u <user> change to user-id\n";
- #print " -g <group> change to group-id (default: primary group of user if -u is given)\n";
- #print " -U <user> change Unix domain socket owner to user-id\n";
- #print " -G <group> change Unix domain socket group to group-id\n";
- exit;
- }
- sub daemonize()
- {
- delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
- $ENV{'PATH'} = $PATHENV; # set new path environment
- chdir $CURRENT_DIR or die "Can't chdir to $CURRENT_DIR: $!\n";
- #setuid(65534) or die "Can't set uid: $!\n"; # nobody
- open(STDIN, "+>/dev/null") or die "Can't open STDIN: $!\n";
- open(STDOUT, "+>&STDIN") or die "Can't open STDOUT: $!\n";
- open(STDERR, "+>&STDIN") or die "Can't open STDERR: $!\n";
- defined(my $tm = fork) or die "Can't fork: $!\n";
- exit if $tm;
- setsid or die "Can't start a new session: $!\n";
- umask 0;
- main();
- }
- sub main
- {
- my ($ListenSocket);
- my ($proc_manager,$request,%req_params);
- $ListenSocket = FCGI::OpenSocket( $SOCKET_ADDRESS, $SOCKET_BACKLOG );
- if (defined($ListenSocket))
- {
- if (defined($PIDFILE))
- {
- open FILE, "> $PIDFILE" or die $!;
- print FILE "$$\n";
- close FILE;
- }
- if (substr($SOCKET_ADDRESS,0,1) eq '/')
- {
- print "chmod($SOCKET_MODE,$SOCKET_ADDRESS)\n";
- chmod(oct($SOCKET_MODE),$SOCKET_ADDRESS);
- }
- $proc_manager = FCGI::ProcManager->new({ n_processes => $CHILDRENS_COUNT, die_timeout => $CHILDRENS_TIMEOUT });
- $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $ListenSocket, &FCGI::FAIL_ACCEPT_ON_INTR );
- $proc_manager->pm_manage();
- if ($request) { request_loop(\$proc_manager,\$request,\%req_params) };
- FCGI::CloseSocket( $ListenSocket );
- if (substr($SOCKET_ADDRESS,0,1) eq '/') {unlink($SOCKET_ADDRESS);}
- if (defined($PIDFILE)) {unlink($PIDFILE);}
- }
- }
- sub request_loop()
- {
- my ($proc_manager_ref)=$_[0];
- my ($request_ref)=$_[1];
- my ($req_params_ref)=$_[2];
- my ($stdin_passthrough,$req_len,$key,$pid_child,$req_count);
- $req_count=1;
- while( $$request_ref->Accept() >= 0 )
- {
- $$proc_manager_ref->pm_pre_dispatch();
-
- #processing any STDIN input from WebServer (for CGI-POST actions)
- $stdin_passthrough ='';
- { no warnings; $req_len = 0 + $$req_params_ref{'CONTENT_LENGTH'}; };
- if (($$req_params_ref{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) )
- {
- my $bytes_read = 0;
- while ($bytes_read < $req_len)
- {
- my $data = '';
- my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
- last if ($bytes == 0 || !defined($bytes));
- $stdin_passthrough .= $data;
- $bytes_read += $bytes;
- }
- }
- #running the cgi app
- if ( (-x $$req_params_ref{SCRIPT_FILENAME}) && #can I execute this?
- (-s $$req_params_ref{SCRIPT_FILENAME}) && #Is this file empty?
- (-r $$req_params_ref{SCRIPT_FILENAME}) #can I read this file?
- ){
- pipe(CHILD_RD, PARENT_WR);
- $pid_child = open(KID_TO_READ, "-|");
- unless(defined($pid_child))
- {
- print("Content-type: text/plain\r\n\r\n");
- print "Error: CGI app returned no output - Executing $$req_params_ref{SCRIPT_FILENAME} failed !\n";
- next;
- }
- if ($pid_child > 0)
- {
- close(CHILD_RD);
- print PARENT_WR $stdin_passthrough;
- close(PARENT_WR);
- while(my $s = <KID_TO_READ>) { print $s; }
- close KID_TO_READ;
- waitpid($pid_child, 0);
- }else{
- foreach $key ( keys %{$req_params_ref}){ $ENV{$key} = $$req_params_ref{$key}; }
- # cd to the script's local directory
- if ($$req_params_ref{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) { chdir $1;}
- close(PARENT_WR);
- close(STDIN);
- #fcntl(CHILD_RD, F_DUPFD, 0);
- syscall(&SYS_dup2, fileno(CHILD_RD), 0);
- #open(STDIN, "<&CHILD_RD");
- exec($$req_params_ref{SCRIPT_FILENAME});
- die("exec failed");
- }
- }else{
- print("Content-type: text/plain\r\n\r\n");
- print "Error: No such CGI app - $$req_params_ref{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
- }
- $req_count++;
- exit if $req_count > $CHILDRENS_MAX_REQ;
- $$proc_manager_ref->pm_post_dispatch();
- }
- }
复制代码 |
|