Thread Tipp: FastCGI mit FCGI oder CGI::Fast als externer Server
(2 answers)
Opened by pq at 2012-08-03 21:57
Nachdem ich sehr lange gebraucht habe, um FastCGI zum laufen zu bringen, da ich über mehrere dokumentations-bugs gestolpert bin, möchte ich hier das ganze als beispiel beschreiben.
Apache-Config: Code: (dl
)
1 FastCgiExternalServer /tmp/myapp.fcgi -host localhost:8888 Ganz wichtig ist hier: Den Daemon startet man selbst von Hand. /tmp/myapp.fcgi ist hier nur ein virtueller Pfad, der nicht existieren sollte. Das Alias mappt dann /myapp auf den externen Server auf port 8888. Alternativ kann man auch einen Socketpfad angeben. Als nächstes versuchte ich, das Skript als Daemon zu starten. Hier meine fehlgeschlagenen Versuche: Zuerst CGI::Fast. Aus der Doku: Code (perl): (dl
)
1 2 3 4 5 6 7 use CGI::Fast; &do_some_initialization(); $ENV{FCGI_SOCKET_PATH} = "sputnik:8888"; $ENV{FCGI_LISTEN_QUEUE} = 100; while ($q = new CGI::Fast) { &process_request($q); } Das probierte ich aus, jedoch wurde beim Start des Skripts gleich ein Request durchlaufen und danach war das Skript zu ende. Also probierte ich stattdessen direkt FCGI. Dokmentation: man findet dort direkt kein Beispiel, aber einen Hinweis auf das im Paket enthaltende remote.pl. Das skript sieht dann so aus: Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 use FCGI; my $socket = FCGI::OpenSocket( ":8888", 5 ); my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket ); my $count; while( $request->Accept() >= 0 ) { print "Content-type: text/html\r\n\r\n"; print ++$count; } FCGI::CloseSocket( $socket ); Das lief auch erstmal. Jetzt brauchte ich natürlich ein CGI-Objekt. Also: Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 13 use FCGI; my $socket = FCGI::OpenSocket( ":8888", 5 ); my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket ); while( $request->Accept() >= 0 ) { my $cgi = CGI->new; my $test = $cgi->param('test'); print "Content-type: text/html\r\n\r\n"; print "test: $test"; } FCGI::CloseSocket( $socket ); Jetzt bemerkte ich, dass $test, wenn einmal gesetzt, nie mehr verschwand. Das CGI-Objekt holte sich also die Daten nicht neu aus dem Request. Die Lösung fand ich über eine Suchmachine. Vor dem CGI->new muss man ein CGI::initialize_globals(); aufrufen. Das hat dann funktioniert. Sollte in der Doku hinzugefügt werden. Jetzt wollte ich noch wissen, warum es mit CGI::Fast nicht ging. Auch hier half mir der Eintrag bei stackoverflow, den ich gefunden hatte: http://stackoverflow.com/questions/7206323/perl-we... Dort ist ein RT-Ticket verlinkt: https://rt.cpan.org/Ticket/Display.html?id=70609 Die Lösung: Die Initialisierungen der Umgebungsvariablen müssen *vor* dem laden der Module passieren. Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 use CGI::Fast; BEGIN { $ENV{FCGI_SOCKET_PATH} = "sputnik:8888"; $ENV{FCGI_LISTEN_QUEUE} = 100; } &do_some_initialization(); while ($q = new CGI::Fast) { &process_request($q); } und die richtig lautenden Beispiele: Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 BEGIN { $ENV{FCGI_SOCKET_PATH} = "localhost:8888"; $ENV{FCGI_LISTEN_QUEUE} = 100; } use CGI::Fast; ... my $count; while (my $cgi = new CGI::Fast) { ... } Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 use FCGI; my $socket = FCGI::OpenSocket( ":8888", 5 ); my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket ); my $count; while( $request->Accept() >= 0 ) { CGI::initialize_globals(); my $cgi = CGI->new; ... } FCGI::CloseSocket( $socket ); Dieses Skript dann einfach starten und der Daemon läuft. Last edited: 2012-08-03 22:04:12 +0200 (CEST) Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wie frage ich & perlintro brian's Leitfaden für jedes Perl-Problem |