项目

一般

个人资料

操作

使用 lighttpd 的应用程序

Lighttpd 适用于大多数 Web 项目。为了便于设置,一些项目提供了特殊的 lighttpd 设置。

使用 Perl 调度器代替 mod_perl

我刚刚收到一封来自 Alex Shah <> 的邮件

我想你可能会想把它包含在发行版中

#!perl
#!/usr/bin/perl
use strict;
use CGI::Fast;
use Embed::Persistent;
{
    my $p = Embed::Persistent->new();
    while (new CGI::Fast) {
        my $filename = $ENV{SCRIPT_FILENAME};
        my $package = $p->valid_package_name($filename);
        my $mtime;
        if ($p->cached($filename, $package, \$mtime))
        {
            eval {$package->handler;};
        }
        else
        {
            $p->eval_file($ENV{SCRIPT_FILENAME});
        }
    }
}

这是 lighttpd.conf

#!perl
fastcgi.server = ( ".pl" =>
    (( "socket"   => "/tmp/application.fcgi.socket",
       "bin-path" => "/Users/ashah/docroot/dispatch.fcgi",
    ))
)

有时会遇到从 CPAN 编译提供 Embed::Persistent 的 ExtUtils 的问题,因此您只能下载它们并将 lib/Embed 复制到您的 perl 路径。您还可以在 http://search.cpan.org/dist/perl/pod/perlembed.pod#Maintaining_a_persistent_interpreter 找到一些信息。

如果上述方法对您不起作用,您也许可以尝试 SpeedyCGIPPerl,它们通过自己的持久化 Perl 解释器持续运行 Perl 脚本。它像普通的 CGI 一样运行,不需要对您的 lighttpd 设置进行任何更改(只需更改脚本中的 shebang 行)。

另一种使用 Perl 调度器代替 mod_perl 的方法

我正在使用 CGI::Application 和 lighty 1.4.11。您唯一需要安装的模块是 CGI::Fast,它是一个纯 Perl 模块。C::A 应用程序在实例脚本中只需少量更改即可正常运行。如果您使用多个实例脚本,则可以使用 CGI::Application::Dispatch。—— 来自 freenode 的 Qiang@cgiapp。

这是我的实例脚本(或调度器)。

#!perl
#!/usr/bin/perl -w
use strict;
use warnings;
use My::App;
use CGI::Fast();

while (my $q = new CGI::Fast){
    my $webapp = My::App->new( QUERY => $q );
    $webapp->run();
}

#### below is what i have for mod_perl. 
#### you can see there isn't much change after migrating to lighty.
#!/usr/bin/perl -w
use strict;
use warnings;
use My::App;
use CGI::Fast;

my $webapp = My::App->new();
$webapp->run();

这是我的 lighty 配置

#!perl
       ### here is the fastcgi server
       $HTTP["host"] == "dev.example.com" {
            var.root    = "/path/to/app/root/" 
            server.document-root = var.root + "htdocs/" 

            url.rewrite = ( "^/static/.*"        => "$0",
                            "^/([a-zA-Z_]+)$"    => "/index.pl/$1",
                            "^/([a-zA-Z_]+/.*)$" => "/index.pl/$1" 
                           )

            fastcgi.server = ( ".pl" => ((
                                 "bin-path"        => var.root + "htdocs/index.pl",
                                 "bin-environment" => ( "PERL5LIB" => var.root + "lib",
                                                        "CGIAPP_CONFIG_FILE" => var.root + "conf/my.conf" ),
                                 "socket"          => "/tmp/perl.socket",
                                 "check-local"     => "disable",
                                 "min-procs"       => 2,
                                 "max-procs"       => 5,
                                 "idle-timeout"    => 20
                 )))
        }

        # this is for plain cgi
        $HTTP["host"] == "dev1.example.com" {
            alias.url  = ( "/bin/" => "/app/htdocs/bin/" )
            $HTTP["url"] =~ "^/bin" {
                    setenv.add-environment = ( "DEVMODE" => "dev" )
                    cgi.assign = ( ".pl" => "/usr/bin/perl" )
            }
        }

一台服务器上的多个 RubyOnRails

http://wiki.rubyonrails.com/rails/show/HowtoDeployMoreThanOneRailsAppOnOneMachine 描述了如何在 Apache 上实现,这里我们将在 lighty 上实现。

#!perl
$HTTP["url"] =~ "^/appOne" {
  url.rewrite = ( "^/appOne(/.*)$" => "/appOne/public$1" )
  fastcgi.server = ( "dispatch.fcgi" => (( "bin-path" ... )))
  server.error-handler-404 = "/appOne/dispatch.fcgi" 
}
$HTTP["url"] =~ "^/appTwo" {
  url.rewrite = ( "^/appTwo(/.*)$" => "/appTwo/public$1" )
  fastcgi.server = ( "dispatch.fcgi" => (( "bin-path" ... )))
  server.error-handler-404 = "/appTwo/dispatch.fcgi" 
}

RunPhp:从 lighttpd 外部生成多个虚拟主机 php

为了理解这个工具的工作原理,我将使用 lighttpd 的 php 问题定义如下。

问题描述

使用 lighttpd,您有两种运行 php 的选择:

  • 让 lighttpd 从内部为虚拟主机生成 PHP-FastCGI 进程,
  • 或者您可以自己从外部生成它,lighttpd 将使用套接字。

我发现 lighttpd 生成 FastCGI 进程不是一个好主意,因为 lighttpd 是一个 Web 服务器,而不是一个外部进程生成器。另一个反驳论点是处理 php 安全模式下的文件,这个问题在我以前使用的 Apache 中也存在。

在 php 安全模式下,代码无法访问不属于其 UID 的文件。当代码创建一个目录时,该目录的 UID 是 Web 服务器的 UID(在我的系统上通常是 www-data),而不是上传文件的用户的 UID。该代码甚至无法 ''chown()'' 文件/目录以使其拥有其 UID。这使得递归目录创建不可用,并且使得一些广泛使用的开源代码——这些代码也使用该方法处理大量文件——也无法使用。

关闭 safe_mode,让用户上传的代码超出 documentroot?我发现这是一个坏主意。

还有另一个问题:如果您为每个虚拟主机使用一个 php 设置(一个 php.ini),那么不同的虚拟主机如何拥有不同的设置?这也是需要的。

解决方案

解决方案是为每个虚拟主机使用一个单独的 PHP FastCGI 进程。但是,如果您有大量虚拟主机,这很难处理,所以我创建了这个工具。现在,php 以站点用户的 UID 运行(在我的情况下,是使用 scp 将文件上传到服务器的用户)。这样,safe_mode 目录和文件创建问题就解决了。例如,Joomla 和其他在 Web 根目录下管理目录和文件的免费门户网站,可以在开启 safe_mode 的情况下使用!

_'_问题:您能解释一下这个工具具体是做什么的吗?如果我查看源代码,它似乎不是一种 suexec 包装器,而是一种用于多个 FastCGI 进程的配置创建器?所以这里我们有对 http://trac.lighttpd.net/trac/wiki/HowToSetupFastCgiIndividualPermissions 中描述的解决方案的自动化——对吗?

RunPhp 在一个配置文件中管理独立且唯一的虚拟主机设置,该文件的格式易于理解,并且可以像 .ini 文件一样处理。

现在,我们来看看如何设置和使用它。

设置、配置和命令行用法

设置:所需程序

  • Python(据我所知,它适用于 python2.2.0 及更高版本)
  • ''/usr/bin/spawn-fcgi'',它可以在 lighttpd 发行版中找到,编译后您必须将其复制到相应位置:从 lighttpd 源代码目录运行 ''"cp src/spawn-fcgi /usr/bin"''
  • 编译为 fcgi 二进制文件的 php(参见 lighttpd 的文档)
  • 正在运行的 lighttpd,用户 ID 为 www-data
  • http://trac.lighttpd.net/trac/attachment/wiki/ApplicationsUsingLighttpd/RunPhp.tar.gz,并将其解压到您的系统上 :-)

配置:如何配置 RunPhp

如果您已安装上述所有内容,请编辑 ''/etc/lighttpd/RunPhp/RunPhp.ini''。您将在此处找到:

#!ini
[examplehost1.exampledomain.com]
# The FCGI socket on your system. This will be used by lighttpd.
fCgiSocket = /tmp/examplehost1.exampledomain.com.php.sock
# php's safe_mode variable
safeMode = On
# php's open_basedir variable
openBaseDir = /var/www/examplehost1.exampledomain.com/examplehost1.exampledomain.com
# php's doc_root variable
docRoot = /var/www/examplehost1.exampledomain.com/examplehost1.exampledomain.com
# php's upload_tmp_dir variable
uploadTmpDir = /var/www/examplehost1.exampledomain.com/examplehost1.exampledomain.com/admin/tmp
# php's zlib_output_compression variable
zlibOutputCompression = On
# php's disable_functions variable
disableFunctions = escapeshellarg,escapeshellcmd,exec,passthru,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,system
# The userid, the spawned php will have this userid
userId = exampleuser1
# The group id, the spawned php will have this group id
groupId = examplegroup1
# php's register_globals variable
registerGlobals = On
# php's magic_quotes_gpc variable
magicQuotesGpc = On
# php's magic_quotes_runtim variable
magicQuotesRuntime = Off
# php's magic_quotes_sybase variable
magicQuotesSybase = Off

[examplehost2.exampledomain.com]
fCgiSocket = /tmp/examplehost2.exampledomain.com.php.sock
safeMode = Off
openBaseDir = /var/www/examplehost2.exampledomain.com/examplehost2.exampledomain.com
docRoot = /var/www/examplehost2.exampledomain.com/examplehost2.exampledomain.com
uploadTmpDir = /var/www/examplehost2.exampledomain.com/examplehost2.exampledomain.com/admin/tmp
zlibOutputCompression = Off
disableFunctions = function1,function2,etc
userId = exampleuser2
groupId = examplegroup2
registerGlobals = Off
magicQuotesGpc = Off
magicQuotesRuntime = Off
magicQuotesSybase = Off

此文件包含现在可用于已生成 PHP-FastCGI 进程的所有设置。您可以根据需要编辑它们。节名称包含虚拟主机的名称,此名称稍后将用于启动/重启一个虚拟主机。请阅读下文了解详情。

您可以为更多虚拟主机添加更多节,它们将在您下次运行 RunPhp 时生成。

命令行用法

为了更方便使用,我将 ''/etc/lighttpd/RunPhp/RunPhp.py_ 符号链接到 _/usr/bin/runphp'',这样如果您正确解压了 tar 包,您将拥有一个 _runphp_ 命令。

命令行用法很简单。

一个简单的 runphp 命令将运行在 ''/etc/lighttpd/RunPhp/RunPhp.ini'' 配置文件中找到的所有节。如果您提供虚拟主机的名称(例如节名称),则只有该虚拟主机将被启动/重启。

调整 RunPhp

如果您需要每个虚拟主机拥有更多独特的变量(在 RunPhp.ini 文件中找不到的配置选项),您可以轻松扩展 RunPhp。我将通过一个例子来展示。

假设我们需要 safe_mode_exec_dir 对每个虚拟主机来说是唯一的,因此我们执行以下操作:

  1. 编辑 ''/etc/lighttpd/RunPhp/php.ini'',这是用于每个生成的 PHP-FastCGI 进程的骨架配置。将 "safe_mode_exec_dir = <something>" 替换为 "safe_mode_exec_dir = safeModeExecDir"(术语区分大小写)
  2. 编辑 ''/etc/lighttpd/RunPhp/RunPhp.py'',在第 56 行和第 57 行之间添加以下行(保持缩进)
'safeModeExecDir' : '<default_value_you_want>',
... 这样,即使您尚未将其添加到 RunPhp.ini 节中,''safe_mode_exec_dir'' 也将具有一个默认值。(当然,将 default_value_you_want 更改为您想要的默认值!)# 编辑您的 ''/etc/lighttpd/RunPhp/RunPhp.ini'',并将 ''"safeModeExecDir = <your_unique_value>"'' 添加到每个节中。这不是必需的,因为如果您正确执行了第二步,safe_mode_exec_dir 将在 Python 源代码中指定一个默认值。在这种情况下,您只需将此行添加到所需的节中。

进行此调整后,您必须重启您希望使用新值的虚拟主机。

就是这样。:-)

有问题吗?

您可以随时联系作者 Laszlo Karolyi (laszlo-AT-karolyi-DOT-hu)。

玩得开心!

Laszlo KAROLYI

更新日志

2007-03-03 更新:我将我的内核从 2.4.x 更改为 2.6.x,并且使用该内核生成的 php ini 文件可能会在被读取和解析之前被删除,所以我更新了脚本,使其不再删除它们。现在它使用一个名为 'createdConfigs' 的目录来保存这些文件,以便 php 可以随时读取它们。

stbuehler 更新,近 13 年前 · 34 次修订