Welcome! Log In Create A New Profile

Advanced

Nginx, FCGI and Perl on Ubuntu 11.04

Posted by J-Tallis 
Nginx, FCGI and Perl on Ubuntu 11.04
September 29, 2011 11:46AM
Hey, I'm having problems setting up Perl to work with Nginx. I have not found many clear tutorials so I'm just doing trial and error. I've connected up the Perl Wrapper, Nginx config and have installed FCGI and of course Perl.

This is my Perl Wrapper - /usr/local/bin/cgiwrap-fcgi.pl
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#!/usr/bin/perl

use strict;
use diagnostics;
use FCGI;
#perl -MCPAN -e 'install FCGI'
use Socket;
use POSIX qw(setsid);
#use Fcntl;

require 'syscall.ph';

#&daemonize;

#this keeps the program alive or something after exec'ing perl scripts
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; };
eval q{exit};
if ($@) {
exit unless $@ =~ /^fakeexit/;
};

&main;

#sub daemonize() {
# chdir '/' or die "Can't chdir to /: $!";
# defined(my $pid = fork) or die "Can't fork: $!";
# exit if $pid;
# setsid or die "Can't start a new session: $!";
# umask 0;
#}

sub main {
my $req_params;

my $socket = FCGI::OpenSocket( "127.0.0.1:8999", 10 ); #use IP sockets
#$socket = FCGI::OpenSocket( "/var/run/nginx/perl_cgi-dispatch.sock", 10 ); #use UNIX sockets - user running this script must have w access to the 'nginx' folder!!
my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \$req_params, $socket );
if ($request) { request_loop($request, $req_params)};
FCGI::CloseSocket( $socket );
}

sub request_loop {
my $request = $_[0];
my %req_params = $_[1];

while( $request->Accept() >= 0 ) {

#processing any STDIN input from WebServer (for CGI-POST actions)
my $stdin_passthrough = '';
my $req_len = 0 + $req_params{'CONTENT_LENGTH'};
if (($req_params{'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{SCRIPT_FILENAME}) && #can I execute this?
(-s $req_params{SCRIPT_FILENAME}) && #Is this file empty?
(-r $req_params{SCRIPT_FILENAME}) #can I read this file?
){
pipe(CHILD_RD, PARENT_WR);
my $pid = open(KID_TO_READ, "-|");
unless(defined($pid)) {
print("Content-type: text/plain\r\n\r\n");
print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
next;
}
if ($pid > 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, 0);
} else {
foreach my $key ( keys %req_params){
$ENV{$key} = $req_params{$key};
}
# cd to the script's local directory
if ($req_params{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{SCRIPT_FILENAME});
die("exec failed");
}
}
else {
print("Content-type: text/plain\r\n\r\n");
print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
}

}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

This is my nginx Configuration file
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
server {
listen 82;

server_name localhost;
root /srv/www/perl/public_html;

location / {
index index.html index.htm;
}

location ~ ^/cgi-bin/.*\.cgi$ {
gzip off;
fastcgi_pass 127.0.0.1:8999;
fastcgi_param SCRIPT_FILENAME /srv/www/perl/public_html$fastcgi_script_name;
include fastcgi_params;
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

My error_log does display some errors when I open up a Perl file on my browser. These are the errors I receive...
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2011/09/29 16:43:07 [error] 14275#0: *1 FastCGI sent in stderr: "Undefined subroutine &main::__NR_dup2 called at /usr/lib/perl/5.10/bits/syscall.ph line 82" while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /cgi-bin/index.cgi HTTP/1.1", upstream: "fastcgi://127.0.0.1:8999", host: "localhost:82"
2011/09/29 16:43:07 [error] 14275#0: *1 upstream closed prematurely FastCGI stdout while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /cgi-bin/index.cgi HTTP/1.1", upstream: "fastcgi://127.0.0.1:8999", host: "localhost:82"

Can you explain what in earth is going on? I cannot figure it out - it's becoming annoying.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Re: Nginx, FCGI and Perl on Ubuntu 11.04
September 30, 2011 11:48AM
OK, I'm new to this as well but I have got it working (and I'm also using cgiwrap-fcgi.pl). Looking at your error message it looks like it is the Perl script that is failing rather than the Nginx setup (check out line 82 of syscall.ph).

1. I set it up using sockets rather than tcp ports. This is what I have in my conf file (note, my scripts have a .pl extension):-

location ~ ^/cgi-bin/.*\.pl$ {
root /usr/local/httpd;
gzip off;
fastcgi_pass unix:/tmp/nginx/perl_cgi-dispatch.sock;
fastcgi_index index.cgi;
fastcgi_param SCRIPT_FILENAME /usr/local/httpd$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}

2. You need to start cgiwrap-fcgi.pl as a background daemon. I set up the following init script (I'm using Centos 6 OS):-


#! /bin/sh

### BEGIN INIT INFO
# Provides: perl-cgiwrap
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# chkconfig: 2345 10 90
# Short-Description: starts cgiwrap-fcgi.pl
# Description: starts the Perl FastCGI Process daemon
### END INIT INFO


PID=`pidof -x /usr/local/bin/cgiwrap-fcgi.pl`

case "$1" in
start)
if ( test $PID ); then
echo "/usr/local/bin/cgiwrap-fcgi.pl is already running"
else
echo "Starting cgiwrap "
/usr/local/bin/cgiwrap-fcgi.pl
fi
;;

stop)
if ( test $PID ); then
echo "Gracefully shutting down cgiwrap "
kill $(pidof -x /usr/local/bin/cgiwrap-fcgi.pl)
else
echo "/usr/local/bin/cgiwrap-fcgi.pl is not running"
fi
;;

restart)
if ( test $PID ); then
echo "Gracefully shutting down cgiwrap "
kill $(pidof -x /usr/local/bin/cgiwrap-fcgi.pl)
fi
sleep 2
echo "Restarting /usr/local/bin/cgiwrap.fcgi.pl"
/usr/local/bin/cgiwrap-fcgi.pl
;;

status)
if ( test $PID ); then
ps -F -p $(pidof -x /usr/local/bin/cgiwrap-fcgi.pl)
else
echo "/usr/local/bin/cgiwrap-fcgi.pl is not running"
fi
;;

*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;

esac

3. Other problems I had were all to do with additional Perl modules that were either missing or incorrectly installed, so make sure that your basic Perl scripts work, first, before trying them from a browser (sorry if I'm teaching grandmum to suck eggs, here).

HTH

Doug
Re: Nginx, FCGI and Perl on Ubuntu 11.04
September 30, 2011 12:34PM
Well, doing 'sudo perl /usr/local/bin/cgiwrap-fcgi.pl&' it does keep a process running... but maybe I do need something else for it... I'm really confused but I am on Ubuntu 11.04 so what you provided probably won't work.
Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 266
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready