Site Tools


software:perl:fastcgi

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
software:perl:fastcgi [2015/05/20 18:25]
– ru:software:fastcgi_perl переименовано в ru:software:perl:fastcgi root
software:perl:fastcgi [2022/02/05 04:02] (current)
root
Line 1: Line 1:
 ====== Perl fastcgi daemon ====== ====== Perl fastcgi daemon ======
-Поставил nginx вместо lighttpd и долго мучался с подключением perl. +Nginx, в отличии от lighttpd не умеет сам выполнять perl скриптыа готовых fcgi демонов для этого не было в 2009 годукогда я перешёл на nginx.\\
-Не нашёл ничего чтобы работало демоном для перла по fast-cgi. +
-Зато было две модификации перлового скриптакоторый как раз и работал по fast-cgi. +
-Пришлось самому его дописывать и делать обёртку стартового скрипта. +
-chroot не тестировал, но работать должнопотому что за основу брался рабочий скрипт от spawn-fcgi из соседней ветки: [url=http://www.netlab.linkpc.net/forum/index.php?topic=6.0]http://www.netlab.linkpc.net/forum/index.php?topic=6.0[/url]+
  
 +----
  
-Пример настроек в rc.conf+<note important>Сейчас, в 2018 я перешёл на [[https://github.com/gnosek/fcgiwrap|fcgiwrap]]. Настраивается предельно просто.</note>\\ 
-[code]perl_fcgi_enable="YES"+Так же хорошо работает uWSGI, инструкции по настройке: [[http://vladimir-stupin.blogspot.nl/2014/08/nginx-php5-fpm-uwsgi.html|Настройка nginx, php5-fpm и uwsgi]] и [[http://uwsgi-docs.readthedocs.io/en/latest/CGI.html|Running CGI scripts on uWSGI]]. Главное не забыть в конфиге nginx <code>uwsgi_modifier1 9;</code> 
 + 
 +---- 
 + 
 +Демон не моя разработка, я нашёл несколько готовых вариантов, доработал их немного, добавил rc.d скрипт для FreeBSD. В коде демона есть отсылки к оригиналам.\\ 
 +Работа chroot не проверялась, остальное вроде работает.\\ 
 +Часть не реализованных в демоне опций выполняется стартовым скриптом (chroot, смена пользователя и группы), часть не реализована (смена владельца и группы на сокете).\\ 
 + 
 +**Стартовый скрипт**: [[http://netlab.linkpc.net/download/software/perl/fastcgi/perl-fcgi|perl-fcgi]] (на FreeBSD расположить в /usr/local/etc/rc.d)\\ 
 +**Демон**[[http://netlab.linkpc.net/download/software/perl/fastcgi/perl-fcgi.pl|perl-fcgi.pl]] (на FreeBSD расположить в /usr/local/etc/ - можно поменять в стартовом скрипте, см выше)\\ 
 +**Лицензия**: BSD\\ 
 + 
 +**Более продвинутый вариант**: [[https://gitorious.org/perl-fpm/perl-fpm/|perl-fpm от NiTr0]]\\ 
 +**Обсуждение на форуме**: [[http://forum.nag.ru/forum/index.php?showtopic=83021|forum.nag.ru]] 
 + 
 + 
 + 
 +===== Пример настроек ===== 
 +В rc.conf для FreeBSD добавляем: 
 +<code>perl_fcgi_enable="YES"
 perl_fcgi_pidfile="/var/run/perl-fcgi.pid" perl_fcgi_pidfile="/var/run/perl-fcgi.pid"
 perl_fcgi_user="www" perl_fcgi_user="www"
Line 14: Line 30:
 perl_fcgi_chdir="/" perl_fcgi_chdir="/"
 perl_fcgi_chroot="" perl_fcgi_chroot=""
-perl_fcgi_socket="/tmp/perl-fcgi.sock"+perl_fcgi_socket="127.0.0.1:53676" 
 +perl_fcgi_socket="/var/run/perl-fcgi.sock"
 perl_fcgi_socketbacklog="100" perl_fcgi_socketbacklog="100"
-perl_fcgi_socketmode="0777"+perl_fcgi_socketmode="1777"
 perl_fcgi_children="2" perl_fcgi_children="2"
 perl_fcgi_childrentimeout="10" perl_fcgi_childrentimeout="10"
-perl_fcgi_max_requests="10000+perl_fcgi_max_requests="100
-perl_fcgi_path_env="/bin:/usr/bin"[/code+perl_fcgi_path_env="/bin:/usr/bin"</code> 
- +  * **enable** - разрешить запуск при загрузке 
- +  * **user** - имя пользователя под которым выполнять демона и скрипты 
-стартовый скрипт perl-fcgi (на FreeBSD ложить в /usr/local/etc/rc.d): +  * **group** группа под которыми выполнять демона и скрипты 
-[code]#!/bin/sh +  * **chdir** текущая директория для демона 
-### Rozhuk Ivan 2009.05 +  * **chroot** корневая директория для демона 
-### startup script file for perl-fcgi +  * **socket** unix сокет путь или ip:port для работы fcgi 
-### +  * **socketbacklog** размер очереди входящих соединений, только для сетевых сокетов 
- +  * **socketmode** - права доступа к сокету, только для unix сокета 
- +  * **children** количество дочерних процессов для выполнения скриптов 
-# PROVIDE: perl_fcgi +  * **childrentimeout** - максимальное время выполнения скрипта 
-# REQUIRE: DAEMON +  * **max_requests** - максимальное количество запросов обработанных одним дочерним процессом 
-# BEFORE:  LOGIN +  * **path_env** - перезаписать переменную окружения PATH
-# 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" +
-[/code] +
- +
- +
-Демонический скрипт perl-fcgi.pl (ложить в /usr/local/etc/ - можно поменять в стартовом скрипте, см выше): +
-[code]#!/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(); +===== Параметры командной строки демона ===== 
- } +  * **-d** <directory- chdir to directory before spawning (default /
-} +  * **-s** <address/path> - unix socket or tcp address:port 
-[/code]+  * **-sb** <size> - socket backlog size (default 10) 
 +  * **-M** <mode> - change Unix domain socket mode (default 0777) 
 +  * **-F** <children> - number of children to fork (default 2) 
 +  * **-Ft** <timeout> - children process timeout (default 30) 
 +  * **-Fm** <num> - children process max requests (default 100) 
 +  * **-P** <path> - name of PID-file for spawned process 
 +  * **-e** <path> - set new PATH environment (default /bin:/usr/bin)
  
  
-Постарался проследить историю развития скрипта, может что то и напутал. +{{tag>software freebsd perl deprecated mysoft}}
-Версию с более продвинутой логикой внутри мне не удалось заставить работать, поэтому я взял версию немного по проще, судя по описанию она не возвращает сообщений об ошибках в скриптах.+
  
-В коде видно часть не реализованных опций - часть из них реализуется стартовым скриптом (chroot, смена пользователя и группы), часть нет (смена владельца и группы на сокете). 
software/perl/fastcgi.1432146339.txt.gz · Last modified: 2015/05/20 18:25 by root