配置Nginx 运行CGI(Perl-cgi)

笔者的nginx安装目录为/usr/local/nginx

虚拟机配置文件为/usr/local/nginx/conf/vhosts.conf

目前php fast-cgi已支持

以下操作均在su下完成

=====================

安装perl cgi模块
wget http://www.cpan.org/modules/by-module/FCGI/FCGI-0.67.tar.gz      
tar -zxvf FCGI-0.67.tar.gz      
cd FCGI-0.67      
perl Makefile.PL     
make && make install

安装FCGI-ProcManager:
wget http://search.cpan.org/CPAN/authors/id/G/GB/GBJK/FCGI-ProcManager-0.18.tar.gz     
tar -xzxf FCGI-ProcManager-0.18.tar.gz      
cd FCGI-ProcManager-0.18      
perl Makefile.PL      
make      make install

===================

先在/bin目录下放置一个perl写的分发器,取名叫perl-fcgi

vi /bin/perl-cgi

  1. #!/usr/bin/perl -w   
  2. use FCGI;   
  3. use Socket;   
  4. use FCGI::ProcManager;   
  5. sub shutdown { FCGI::CloseSocket($socket); exit; }   
  6. sub restart  { FCGI::CloseSocket($socket); &main; }   
  7. use sigtrap 'handler', \&shutdown, 'normal-signals';   
  8. use sigtrap 'handler', \&restart,  'HUP';   
  9. require 'syscall.ph';   
  10. use POSIX qw(setsid);   
  11.     
  12. #&daemonize; we don't daemonize when running under runsv   
  13. #this keeps the program alive or something after exec'ing perl scripts   
  14. END()   { }   
  15. BEGIN() { }   
  16. {   
  17.     no warnings;   
  18.     *CORE::GLOBAL::exit = sub { die "fakeexit\nrc=" . shift() . "\n"; };   
  19. };   
  20. eval q{exit};   
  21. if ($@) {   
  22.     exit unless $@ =~ /^fakeexit/;   
  23. }   
  24. &main;   
  25.     
  26. sub daemonize() {   
  27.     chdir '/' or die "Can't chdir to /: $!";   
  28.     defined( my $pid = fork ) or die "Can't fork: $!";   
  29.     exit if $pid;   
  30.     setsid() or die "Can't start a new session: $!";   
  31.     umask 0;   
  32. }   
  33.     
  34. sub main {   
  35.     
  36.      $socket = FCGI::OpenSocket( "127.0.0.1:10081"10 ); #use IP sockets   
  37.     #$socket = FCGI::OpenSocket( "/var/run/nginx/perl_cgi-dispatch.sock", 10 );    
  38.     #use UNIX sockets - user running this script must have w access to the 'nginx' folder!!   
  39.     #foreach $item (keys %ENV) { delete $ENV{$item}; }   
  40.     $proc_manager = FCGI::ProcManager->new( {n_processes => 5} );   
  41.     #$socket = FCGI::OpenSocket( "/opt/nginx/fcgi/cgi.sock", 10 )   
  42.         ; #use UNIX sockets - user running this script must have w access to the 'nginx' folder!!   
  43.     $request =   
  44.         FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket,   
  45.         &FCGI::FAIL_ACCEPT_ON_INTR );   
  46.     $proc_manager->pm_manage();   
  47.     if ($request) { request_loop() }   
  48.     FCGI::CloseSocket($socket);   
  49. }   
  50.     
  51. sub request_loop {   
  52.     while ( $request->Accept() >= 0 ) {   
  53.         $proc_manager->pm_pre_dispatch();   
  54.     
  55.         #processing any STDIN input from WebServer (for CGI-POST actions)   
  56.         $stdin_passthrough = '';   
  57.         { no warnings; $req_len = 0 + $req_params{'CONTENT_LENGTH'}; };   
  58.         if ( ( $req_params{'REQUEST_METHOD'} eq 'POST' ) && ( $req_len != 0 ) )   
  59.         {   
  60.             my $bytes_read = 0;   
  61.             while ( $bytes_read < $req_len ) {   
  62.                 my $data = '';   
  63.                 my $bytes = read( STDIN, $data, ( $req_len - $bytes_read ) );   
  64.                 last if ( $bytes == 0 || !defined($bytes) );   
  65.                 $stdin_passthrough .= $data;   
  66.                 $bytes_read += $bytes;   
  67.             }   
  68.         }   
  69.     
  70.         #running the cgi app   
  71.         if (   
  72.             ( -x $req_params{SCRIPT_FILENAME} ) &&    #can I execute this?   
  73.             ( -s $req_params{SCRIPT_FILENAME} ) &&    #Is this file empty?   
  74.             ( -r $req_params{SCRIPT_FILENAME} )       #can I read this file?   
  75.             )   
  76.         {   
  77.             pipe( CHILD_RD,   PARENT_WR );   
  78.             pipe( PARENT_ERR, CHILD_ERR );   
  79.             my $pid = open( CHILD_O, "-|" );   
  80.             unless ( defined($pid) ) {   
  81.                 print("Content-type: text/plain\r\n\r\n");   
  82.                 print  
  83. "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";   
  84.                 next;   
  85.             }   
  86.             $oldfh = select(PARENT_ERR);   
  87.             $|     = 1;   
  88.             select(CHILD_O);   
  89.             $| = 1;   
  90.             select($oldfh);   
  91.             if ( $pid > 0 ) {   
  92.                 close(CHILD_RD);   
  93.                 close(CHILD_ERR);   
  94.                 print PARENT_WR $stdin_passthrough;   
  95.                 close(PARENT_WR);   
  96.                 $rin = $rout = $ein = $eout = '';   
  97.                 vec( $rin, fileno(CHILD_O),    1 ) = 1;   
  98.                 vec( $rin, fileno(PARENT_ERR), 1 ) = 1;   
  99.                 $ein    = $rin;   
  100.                 $nfound = 0;   
  101.     
  102.                 while ( $nfound =   
  103.                     select( $rout = $rin, undef, $ein = $eout, 10 ) )   
  104.                 {   
  105.                     die "$!" unless $nfound != -1;   
  106.                     $r1 = vec( $rout, fileno(PARENT_ERR), 1 ) == 1;   
  107.                     $r2 = vec( $rout, fileno(CHILD_O),    1 ) == 1;   
  108.                     $e1 = vec( $eout, fileno(PARENT_ERR), 1 ) == 1;   
  109.                     $e2 = vec( $eout, fileno(CHILD_O),    1 ) == 1;   
  110.     
  111.                     if ($r1) {   
  112.                         while ( $bytes = read( PARENT_ERR, $errbytes, 4096 ) ) {   
  113.                             print STDERR $errbytes;   
  114.                         }   
  115.                         if ($!) {   
  116.                             $err = $!;   
  117.                             die $!;   
  118.                             vec( $rin, fileno(PARENT_ERR), 1 ) = 0  
  119.                                 unless ( $err == EINTR or $err == EAGAIN );   
  120.                         }   
  121.                     }   
  122.                     if ($r2) {   
  123.                         while ( $bytes = read( CHILD_O, $s, 4096 ) ) {   
  124.                             print $s;   
  125.                         }   
  126.                         if ( !defined($bytes) ) {   
  127.                             $err = $!;   
  128.                             die $!;   
  129.                             vec( $rin, fileno(CHILD_O), 1 ) = 0  
  130.                                 unless ( $err == EINTR or $err == EAGAIN );   
  131.                         }   
  132.                     }   
  133.                     last if ( $e1 || $e2 );   
  134.                 }   
  135.                 close CHILD_RD;   
  136.                 close PARENT_ERR;   
  137.                 waitpid( $pid, 0 );   
  138.             } else {   
  139.                 foreach $key ( keys %req_params ) {   
  140.                     $ENV{$key} = $req_params{$key};   
  141.                 }   
  142.     
  143.                 # cd to the script's local directory   
  144.                 if ( $req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/ ) {   
  145.                     chdir $1;   
  146.                 }   
  147.                 close(PARENT_WR);   
  148.     
  149.                 #close(PARENT_ERR);   
  150.                 close(STDIN);   
  151.                 close(STDERR);   
  152.     
  153.                 #fcntl(CHILD_RD, F_DUPFD, 0);   
  154.                 syscall( &SYS_dup2, fileno(CHILD_RD),  0 );   
  155.                 syscall( &SYS_dup2, fileno(CHILD_ERR), 2 );   
  156.     
  157.                 #open(STDIN, "<&CHILD_RD");   
  158.                 exec( $req_params{SCRIPT_FILENAME} );   
  159.                 die("exec failed");   
  160.             }   
  161.         } else {   
  162.             print("Content-type: text/plain\r\n\r\n");   
  163.             print  
  164. "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";   
  165.         }   
  166.     }   
  167. }  

给这个脚本执行权限

chmod +x  /bin/perl-fcgi
然后试试看能否启动
/bin/perl-cgi &
若是成功则会出现以下信息
FastCGI: server (pid 21315): initialized
FastCGI: manager (pid 17915): server (pid 21315) started

如果遇到错误Can’t locate FCGI.pm,那么执行下面的命令

perl -MCPAN -e 'install FCGI'

perl -MCPAN -e 'install FCGI::ProcManager'

cd /usr/include; h2ph *.h */*.h

第一、二条命令是给perl安装FCGI模块,第三条是注册perl能识别的头文件,然后重新执行/bin/perl-fcgi, 如果正常的话,那么执行:

netstat -tunlp

列表中应该出现
tcp        0      0 127.0.0.1:10081             0.0.0.0:*                   LISTEN      5640/perl
启用分发器

/bin/perl-fcgi > /dev/null 2>&1 &
将其写入rc.local
echo "/bin/perl-fcgi > /dev/null 2>&1 &" >> /etc/rc.local
上面的方式启动后perl-fcgi是以执行它的用户身份运行的,对于web程序来说这是很不利的。老外用perl写了一个脚本Noah Friedman可以用指定的用户来运行某个程序,源程序在这里,这里也贴出来方便查阅

相关推荐