第十三章 网页服务器

我们最常使用的网络应用莫过于网页服务器了, 这里我们将介绍如何安装一个功能完整的网页服务器。读完本章后,您可以了解下列网页服务器的管理项目:

13.1 概论

Apache 是 UNIX 系统中普遍使用的网页服务器软件。根据  Netcraft 的统计 (http://news.netcraft.com/archives/web_server_survey.html),目前因特网中,有超过百分之 六十的服务器是使用 Apache 来提供网页浏览的服务。Apache 可以说是目前世界上使用人数最多的网页服务器软件,它不仅可以在 FreeBSD、UNIX、Linux 中运行,也可以安装在 Windows 操作系统中。

Apache 和 FreeBSD 一样,在软件版本上也有多个分支,目前较稳定的版本有 1.3.33 及 2.0.x。Apache 1.3 系列开发已久,已经十分稳定了,不会再有重大的修改。而 Apache 2 系列是一个开发较活跃的版本,它和 1.3 最大的不同在于多执行绪 (multithreaded) 的支援。目前 Apache 2.0.x 是最主要的稳定版本,而 2.1.x 则还处于开发中的状态。笔者建议您使用 Apache 2.0 来做为您的网页服务器。

Apache 之所以风行的原因,除了免费、历史悠久、稳定外,它提供了弹性化的接口,可以让我们依需求加入各种模块,以提供更强大的功能。例如,我们可以在网页服务器上加入 PHP,以支持更多的网页应用。PHP 是一个用来写网页程序的软件,就像 ASP、JAVA servlet、CGI 等等有类似的用途,我们可以使用 PHP 建立留言版、电子相簿、购物车等应用。PHP 十分容易学习,程序代码也很简洁,速度更是没话说。如果你有些微的程序语言基础,不出二个礼拜,你就能对 PHP 有十足的认识,并且可以自己写出留言版、权限控制等简单的程序。

如果要使用 PHP,那你一定也要使用一套数据库系统做为程序后端的数据储存。在众多免费的数据库软件中,最有名的应该是 MySQL 和 PostgreSQL 了。不论是 MySQL 或 PostgreSQL,它们的功能及速度都令人赞赏。使用 PHP 加上数据库软件,你可以制作出网页的各式数据库,如会员管理、产品数据库等等。总之,我十分建议使用 Apache+PHP+数据库的组合,就算目前不会用到,不久的将来也会使用它们的功能。全部一股脑的装起来,省得日后麻烦。

目前 PHP 一样有二个主要的版本分支:4.x 及 5.x,4.4.0 是目前 4.x 的最新版本,而 5.0.x 则是 5.x 中的稳定版。我们将介绍如何使用 PHP 5.0 及数据库。

13.2 安装及设定 Apache

13.2.1使用 ports 安装

使用 FreeBSD port 安装 Apache  十分容易,我们只要使用下列指令即可完成安装:

# cd /usr/ports/www/apache2
# make install clean

我们已经完成了最基本的 Apache 服务器安装,如果您不需要支持 PHP 及数据库,可以跳过下列步骤。

安装 PHP

# cd /usr/ports/www/mod_php5
# make install clean

执行了上述指令后,会出现一个窗口让您选择进阶设定,请记得选取 APACHE2,如下图所示:

图 13-1

接下来我们必须安装一些常用的 PHP 模块,请执行下列指令:

# cd /usr/ports/lang/php5-extensions
# make install clean

执行了 make install 后,会出现一个选单,除了预设的项目外,我们必须再选择下列几个常用的项目:CTYPE、EXIF、GD、ICONV、IMAP、PCRE、SESSION、ZLIB。这些项目非常常用,尤其是 SESSION。

安装完 PHP 后,我们将下来要安装数据库,您可以选择安装 MySQL 或 PostgreSQL,或者干脆二者都安装,以利日后使用不同的数据库应用。

安装 MySQL

# cd /usr/ports/databases/mysql41-server
# make WITH_CHARSET=big5 WITH_XCHARSET=all install clean
# cd /usr/ports/databases/php5-mysql
# make install clean

安装 PostgreSQL

# cd /usr/ports/databases/postgresql80-server
# make install clean
# cd /usr/ports/databases/php5-pgsql
# make install clean

安装了 MySQL 及 PostgreSQL 后,必须再进行数据库的细部设定。相关的数据库详细设定说明,请参考「数据库系统」一章的说明。

13.2.2 Apache 基本设定

安装完 Apache 后,我们必须先进行一些基本设定才可以开始使用。本节中,我们先介绍较常使用的设定项目,让您可以快速的设定好网页服务器,而更详细的 Apache 设定将于下一小节中说明。Apache 的设定档位于 /usr/local/etc/apache2/httpd.conf,请使用文章编辑软件打开 httpd.conf

我们按照设定项目在 httpd.conf 中出现的顺序说明每一个项目,您可以使用搜寻的方式查找每一个项目的关键词,以进行设定。

ServerAdmin 设定管理者邮件

设定您的信箱,这个信箱地址当网页出现错误讯息时将出现在该页面上。以下范例为默认值:

ServerAdmin you@example.com

ServerName 设定主机名称及端口号

ServerName 可以让您设定您的主机名称,如果您没有主机名称,可以设定为您机器所使用的 IP。ServerName 会被用来重新转向网址,例如,当您输入一个网址 「http://www.example.com/dir」时,Apache 会参考您在 ServerName 中的设定,将 www.example.com 改成 ServerName,并在您所输入的网址后加上一个斜线「/」以连到 dir 目录中,也就是将网址转向到「http://www.example.com/dir/」。如果您的网址设定不正确,则使用者可能会连到一个不存在的地址。

所以,如果您没有主机名称,可以将这个值设定为 IP,让网址转向后还是可以连到正确的地方。在 ServerName 的设定中,我们也指定了 HTTP 的连接埠 80。

如果您的服务器是位于 NAT 后面,使用 NAT 做 Port Forwarding,建议不要设定这个项目,改将下一个设定选项 UseCanonicalName 设为 On,才不会在转向网址时导到错误的位置。

ServerName www.example.com:80

UseCanonicalName 设定导向网址的方式

Apache 在导向网址时,会参考您所设定的服务器名称及端口号,但当主机使用 NAT Port Forwarding 时,主机名称及端口号可能会不同,这时候我们必须将这个选项设为 On,以免 Apache 转向到错误的地址。

UseCanonicalName Off

DocumentRoot 设定网页根目录

DocumentRoot 可以让我们指定网页根目录的位置,也就是我们存放网页的目录。

DocumentRoot "/usr/local/www/data"

设定好 DocumentRoot 后,我们必须要再设定该目录的权限。在 DocumentRoot 之后,有下列区段:

<Directory "/usr/local/www">
   Options Indexes FollowSymLinks
   AllowOverride None
   Order allow,deny
   Allow from all
</Directory>

您必须将 <Directory "/usr/local/www"> 也改成您的网页根目录位置。

DirectoryIndex 指定预设网页档名

当使用者使用网址「http://www.example.com/dir」连到一个目录中时,如果没有指定网页,Apache 会去查找 DirectoryIndex 中所设定的网页在不在,如果存在则秀出预设的网页。

预设的网页只有二个,我们可以再加上 index.htm、index.php 等常用的网页:

DirectoryIndex index.php index.htm index.html index.html.var

加入 PHP 支持

如果您要使用 PHP,则必须在 httpd.conf 中加入 PHP 的支持,请在 httpd.conf 档案最后加入下列内容:

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

上述设定完成后,您就可以存盘离开。

接下来,我们必在修改 /etc/rc.conf ,并加入下列设定以在开机时启动 Apache:

apache2_enable="YES"

最后,我们就可以使用下列指令以启动 Apache 了:

# /usr/local/etc/rc.d/apache2.sh start

如果您要停止 Apache,可以使用下列指令:

# /usr/local/etc/rc.d/apache2.sh stop

我们可以在网页根目录中新增一个档案来测试 PHP 是否有正常运作,请使用文书编辑软件开一个新文件 test.php,并加入下列内容:

<?
phpinfo();
?>

接下来您就可以连到该网页 http://192.168.0.1/test.php (请将 192.168.0.1 改成您的主机 IP) 看看是否可以使用 PHP。如果有支持 PHP,则会显示 PHP 组态,如果没有,则只会出现上述档案内容。

13.3 http.conf 说明

/usr/local/etc/apache2/httpd.conf 是 Apache 的主要设定档。档案中有 # 为开头者是批注,用以说明设定的情形及方式,如果一行的开头有 # 的话,该行对 Apache 就不会产生作用。

我们按照 httpd.conf 中各选项出现的顺序说明几个重要的项目,比较不可能更动的项目我们就不在此说明。这些细部 Apache 的设定看起来有点无趣,但不看过一遍不知道有什么是我们可以调整的项目。建议您先大略浏览过即可,日后有调整的需要时,再回过头来参考即可。

ServerRoot 设定 Apache 执行的根目录

ServerRoot 用以设定 Apache 的根目录位置,记录文件、设定文件的相对目录位置。

ServerRoot "/usr/local"

必须注意的是,如果您的此目录设定为 NFS 或是其它以网络挂入的档案系统中,请先阅读 http://httpd.apache.org/docs-2.0/mod/mpm_common.html#lockfile 关于 LockFile 的说明,以避免一些不必须的问题发生。另外,请勿在 ServerRoot 的路径名称最后面加入 "/" 符号。

LockFile 设定 lock 文件的位置

LockFile 通常只有在您的网页数据使用 NFS 挂入时才会需要设定,否则使用默认值即可。如果您有设定 LockFile,LockFile 必须设定在非网络挂入的档案系统中。

<IfModule !mpm_winnt.c>
<IfModule !mpm_netware.c>
#LockFile /var/log/accept.lock
</IfModule>
</IfModule>

我们看到 LockFile 这个项目被 <IfModule !mpm_winnt.c> </IfModule> 包起来,这表示当没有使用 winnt 模块时这个设定才会生效。在下列其它设定中,我们会看到有其它的选项也是以 <IfModule> </IfModule> 包起来,意思是一样的。

PidFile 设定 httpd.pid 位置

Apache 在启动时,会将自己的 process id 写入 PidFile 中。

<IfModule !mpm_netware.c>
PidFile /var/run/httpd.pid
</IfModule>

Timeout 设定联机逾时

Timeout 设定了等待 Client 端响应的时间,以秒为单位。如果 Client 端在指定的时间内没有传送任何数据,即切断联机。

Timeout 300

KeepAlive 是否使用保持联机

设定是否使用保持联机的功能 (Presistent Connections)。当 KeepAlive 设为 On 时,一个已经建立的联机会用来处理多个 HTTP 的请求,也就是一个联机会用来传送多个档案,以避免每一个请求都要重新建立新的联机而降低效能。您可以将 KeepAlive 设为 Off 以关闭保持联机的功能。

KeepAlive On

MaxKeepAliveRequests 最多有几个保持联机

设定最多可以有几个 KeepAlive 的联机。您可以将这个项目设为 0 表示无限制。当有太多的保持联机时,会造成系统资源占用太多。但如果是一个忙录的服务器,建议您提高限制,以增加执行效率。

MaxKeepAliveRequests 100

KeepAliveTimeout 保持联机的逾时时间

同一个 Client 的「保持联机」功能,在多少秒后没有联机的请求即为联机逾时。如果二次请求的时间超过这个设定值,联机就会中断。

KeepAliveTimeout 15

prefork MPM 控制 process 数量

您会看到有很多个 StartServers、MinSpareServers、MaxClients 等设定,每个设定都使用 <IfModule> </IfModule> 包起来。这是因为不同的平台会使用不同的模块,而设定就会依平台而有所不同。在 FreeBSD 中,我们使用的是 perfork 这个模块,因此,我们只要设定这个模块中的值即可。

在这个群组中,各个项目所代表的意义如下:

 

<IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>

Listen 设定接受联机的 IP 及埠号

设定 Apache 所要使用的连接埠号。预设的 HTTP 连接埠为 80,我们使用默认值即可,所以我们使用默认值即可。如果您希望 Apache 只接受连到某一个 IP 的联机 (当您同一台主机有多个 IP 时),可以设定只监听某一个 IP、埠号的联机。

例如,我们可以设定只接受客户端连到 192.168.0.1 的连接埠 8000,则可以设定为 192.168.0.1:8000。

Listen 80

LoadModule 动态加载的模块

Apache Dynamic Shared Object (DSO) 允许我们在启动 Apache 时动态加载模块,例如加载认证模块、PHP 模块等。在这个区段中,您可以看到 Apache 加载了很多模块。我们之后在设定虚拟主机、目录模限控制时,都必须检查 Apache 是否有加载我们想要的模块。这个部份的设定只要保持默认值即可。

LoadModule access_module libexec/apache2/mod_access.so
LoadModule auth_module libexec/apache2/mod_auth.so
LoadModule auth_anon_module libexec/apache2/mod_auth_anon.so
LoadModule auth_dbm_module libexec/apache2/mod_auth_dbm.so
... 略 ...

ExtendedStatus 显示详细状态信息

Apache 有一个 CGI 可以显示 Apache 服务器的状态信息 (server-status),当 ExtendedStatus 打开后,会显示更多信息。我们会在本章下一小节中说明如何使用这些信息。

#ExtendedStatus On

User Group 设定执行时的使用者及群组

系统要使用什么使用者名称及群组执行 Apache。使用 FreeBSD ports 安装后,预设的使用者及群组为 www。

User www
Group www

ServerAdmin 设定邮件

设定您的 Email。这个 Email 会显示在一些由 Apache 所产生的页面中。例如,当使用者连到一个不存在的网页、或是网页发生错误时,Apache 会秀出您所设定的 Email。

ServerAdmin you@example.com

ServerName 设定主机名称

ServerName 可以让您设定您的主机名称,如果您没有主机名称,可以设定为您机器所使用的 IP。ServerName 会被用来重新转向网址,例如,当您输入一个网址 「http://www.example.com/dir」时,Apache 会参考您在 ServerName 中的设定,将 www.example.com 改成 ServerName,并在您所输入的网址后加上一个斜线「/」以连到 dir 目录中,也就是将网址转向到「http://www.example.com/dir/」。如果您的网址设定不正确,则使用者可能会连到一个不存在的地址。

所以,如果您没有主机名称,可以将这个值设定为 IP,让网址转向后还是可以连到正确的地方。在 ServerName 的设定中,我们也指定了 HTTP 的连接埠 80。

如果您的服务器是位于 NAT 后面,使用 NAT 做 Port Forwarding,建议不要设定这个项目,改将下一个设定选项 UseCanonicalName 设为 On,才不会在转向网址时导到错误的位置。

ServerName www.example.com:80

UseCanonicalName 设定导向网址的方式

Apache 在导向网址时,会参考您所设定的服务器名称及端口号,但当主机使用 NAT Port Forwarding 时,主机名称及端口号可能会不同,这时候我们必须将这个选项设为 On,以免 Apache 转向到错误的地址。

UseCanonicalName Off

DocumentRoot 设定网页根目录

DocumentRoot 可以让我们指定网页根目录的位置,也就是我们存放网页的目录。除非您有使用 symbolic links 或是 aliases,否则所有的网页都会放在这个目录中。

DocumentRoot "/usr/local/www/data"

<Directory> 设定目录权限

接下来的几个区段中,您会看到 <Directory> </Directory> 的设定。这个设定是用来指定某个目录的存取权限,例如是否允许执行 CGI、是否要列出该目录下的所有档案等等。

我们以之前所设定的网页根目录「DocumentRoot」为例,当您修改了网页根目录后,您也必须将这个区段中的 <Directory "/usr/local/www"> 改成您的网页目录。由于 Apache 将一般的网页和 CGI 分别放在不同的目录,所以您的 DocumentRoot 设定和这里的设定稍有不同。但您可以将 <Directory> 及 DocumentRoot 都改成 /home/www。

<Directory "/usr/local/www">

#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs-2.0/mod/core.html#options
# for more information.
#
    Options Indexes FollowSymLinks

#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
    AllowOverride None

#
# Controls who can get stuff from this server.
#
    Order allow,deny
    Allow from all

</Directory>

我们后续再来说明一下 <Directory> </Directory> 这个区段中每个项目的用途。

Options 设定目录可以使用的功能

我们在 <Directory> </Directory> 中指定了要设定哪一个目录后,可以再使用 Option 来设定该目录可以使用哪些功能。以下为功能的列表及说明:

当我们对目录设定 Option 的项目后,它的子目录也会继承该目录的设定值。如果我们同时设定一个目录及其子目录的 Option 的设,会以最接近的目录设定为主。例如,我们为 /home/www 及 /home/www/photo 设定权限如下:

<Directory /home/www>
    Options Indexes FollowSymLinks
</Directory>

<Directory /home/www/photo>
    Options Includes
</Directory>

我们设定了 /home/www 可以使用 Indexes 及 FollowSymLinks,但 /home/www/photo 只能使用 Includes。虽然 /home/www/photo 是 /home/www 的子目录,但是其目录的设定只会以自己的 Options 为主,也就是不具有 Indexes 及FollowSymLinks,只有 Includes 的权限。

如果您希望子目录可以继承上一层的设定,可以使用 + 及 - 的符号表示。例如:

<Directory /home/www>
    Options Indexes FollowSymLinks
</Directory>

<Directory /home/www/photo>
    Options +Includes -Indexes
</Directory>

我们在 /home/www/photo 的 Option 中使用了 + 及 -,所以它会继承 /home/www 的设定,但是加上 Includes 的功能,并取消 Indexes,所以最后 /home/www/photo 的权限就是 Includes 及 FollowSymLinks。

AllowOverride 设定 .htaccess 中可以使用的项目

Apache 允许使用者对于目录中使用 .htaccess 文件来控制权限,例如使用密码保护、设定权限等。我们会在下一章中说明如何使用 .htaccess 来做密码保护。

您可以将 AllowOverride 设成 All 或 None 来表示允许或不允许。或者,您也可以指定只允许下列某几个功能:

Order 设定 Allow 及 Deny 的顺序

我们可以在目录中设定允许 (Allow) 及拒绝 (Deny) 的规则先后顺序,当二者抵触时,以后者为主。以下列范例为例,我们先设定了 Order 为 Deny, Allow,再设定拒绝所有联机,但只允许 192.168.0.2 来存取 /home/www/mp3。

<Directory /home/www/mp3>
    Order Deny,Allow
    Deny from all
    Allow from 192.168.0.2
</Directory>

UserDir 设定使用者个人网页

在 mod_userdir 区段中,包含了使用者个人网页的设定。使用者可以使用 http://www.example.com/~username 连到个人网页。预设的设定是每个使用者都可以在自己的家目录中建立一个名为 putblic_html 的目录,该目录就使用者的个人网页目录。UserDir 这个项目即定义了使用者个人网页的路径名称。如果您觉得这个名称太长,更改它的设定,但记得要修改 <Directory> 中的相对设定。

如果您不想让使用者有个人网页,可以将这个区段前面使用 # 批注起来。

<IfModule mod_userdir.c>
UserDir public_html

UserDir disabled root toor daemon ..... pop www nobody mailnull smmsp

#
# Control access to UserDir directories. The following is an example
# for a site where these directories are restricted to read-only.
#
<Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    <Limit GET POST OPTIONS PROPFIND>
        Order allow,deny
        Allow from all
    </Limit>
    <LimitExcept GET POST OPTIONS PROPFIND>
        Order deny,allow
        Deny from all
    </LimitExcept>
</Directory>

</IfModule>

DirectoryIndex 设定预设网页档名

当使用者使用网址「http://www.example.com/dir」连到一个目录中时,如果没有指定网页,Apache 会去查找 DirectoryIndex 中所设定的网页在不在,如果存在则秀出预设的网页。

预设的网页只有二个,我们可以再加上 index.htm、index.php 等常用的网页:

DirectoryIndex index.php index.htm index.html index.html.var

HostnameLookups 设定将客户端 IP 转为 hostname

是否要在 Apache 的记录文件中将 Client 的 IP 转成 hostname。由于将 IP 转成 hostname 需要一点时间,将这个功能设为 On 会造成联机的效率变慢很多。

HostnameLookups Off

ErrorLog 指定错误记录文件位置

设定 Apache 错误讯息的记录文件位置。

ErrorLog /var/log/httpd-error.log

CustomLog 指定联机记录文件位置

设定 Apache 联机记录文件的位置。

CustomLog /var/log/httpd-access.log combined

Alias 设定别名

我们可以为一个目录或联机的 URI 设定别名,以简化目录名称。例如,您可以将 /home/alex/mp3/ 取一个别名为 /mp3/,让使用者在联机到 http://www.example.com/mp3/ 时,指向 /home/alex/mp3/。

Alias /mp3/ /home/alex/mp3/

别名可以设定很多个,您可以依需求简化连结的位置。设定的别名目录不一定要是 DocumentRoot 的子目录,我们可以指定网页根目录以外的目录。

小提示

为了精准起见,我们使用 /mp3/ 而非 /mp3,以免将 /mp3files 变成了 /home/alex/mp3files。也就是多加了一个 "/" 在 mp3 之后。

AliasMatch 使用常规表示的别名

除了一般的别名外,我们还可以使用常规表示来设定别名。例如,我们要设定所有要使用 *.php 的档案都连到 /usr/local/php 目录中,则可以使用:

AliasMatch ^(.+\.php)$ /usr/local/php$1

ScriptAlias 设定 CGI 目录

ScriptAlias 可以让我们设定 CGI 的所在目录,它的功用其实看 Alias 差不多。下面的范例就是当使用者要连到 http://www.example.com/cgi-bin/ 时,我们将 cgi-bin 指向 /usr/local/www/cgi-bin/ 目录中。

ScriptAlias /cgi-bin/ "/usr/local/www/cgi-bin/"

ErrorDocument 指定错误讯息页面

当使用者连到一个不存在的网页,或是网页发生错误时,Apache 预设会帮我们产生一个错误讯息的网页。我们可以修改这个设定,以秀出我们自己设定的页面。例如,当您连到 YAHOO! 时,如果网页不存在,它的页面中还是秀出一些 YAHOO 自己的信息。

在 ErrorDocument 之后,首先要加的是错误代码。错误代码 404 在 HTTP 协议中表示找不到页面。在下列设定中,我们设定当找不到页面时,就秀出 /missing.html。/missing.html 的「/」指的并非系统的根目录,而是您网页的根目录。

ErrorDocument 404 /missing.html

 

小提示

修改 httpd.conf 是调校 Apache 的第一步,更多关于 Apache 的调校,可以参考 Apache 的使用手册,或是参考 http://httpd.apache.org/docs/2.0/misc/perf-tuning.html

13.4 PHP 进阶设定

php.ini 是 PHP 的设定档,若您使用 ports 安装,则你必须将设定文件范例 /usr/local/etc/php.ini.dist 复制成 /usr/local/etc/php.ini。我们可以经由修改 php.ini 来调整 PHP 的功能。

php.ini 中,开头为 ";" 的项目为批注、以 [ ] 包起来的是区段的名称,二种都不会代表任何意义。在修改完 php.ini 后,我们必须也要重跑 Apache 才可以有作用。

以下就让我们针对最常调整的几个项目做说明。

max_execution_time

这个选项设定了 PHP scripts 最长的执行时间,如果您的 PHP 程序需要执行很长的时间,则可以将它延长。预设的最长执行时间是 30 秒。

max_execution_time = 30

memory_limit

设定每一个 scripts 所能耗用的内存大小,预设是 8 MB。

memory_limit = 8M

error_reporting

预设的错误回报内容为何。这个选项设定了 PHP scripts 在发生何种错误时要回报讯息。预设是除了 NOTICE 及 STRICT 的错误以外都回报。这个选项的设定使用了 bit operation,在 php.ini 运算表示式可以使用「|」表示 bit OR、「&」表示 AND、「~」表示 NOT。以下列范例而言,就是 E_ALL AND (NOT E_NOTICE) AND (NOT E_STRICT)。

error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT

error_log

我们可以将错误讯息记录在档案中,或是使用 syslog 将错误记录在 /var/log/messages 中。以下的范例即是使用 syslog。

error_log = syslog

register_globals

PHP 自从 4.1.0 开始,支持一种比较安全的变量传递方式。原本我们在写 PHP 程序时,从窗体以 POST 方式传入 PHP 程序时,PHP 可以直接拿来使用。例如,有一个窗体是下面这个样子:

<form action=test.php method=post>
<input type=text name=username size="20">
<input type=button value=送出 name=b1>
</form>

当上述的 HTML 按了送出之后,在 test.php 这个程序就会有一个变量名为 $username,其值是我们所填入的名称。

但是使用者也可以直接在网址列输入 http://url/test.php?username=myname 来设定 $username 这个变量的值为 myname。

这会有什么问题呢?让我们以 PHP 4.1.0 release note 所提出的例子来说明。假设我们有一个程序如下:

<?php
if (authenticate_user()) {
	$authenticated = true;
}
...
?>

使用者可以经由网址列输入一个变量 $authenticated=true,这样一来,不管是否通过 authenticate_user() 的检查,$authenticated 永远都是 true。

所以在 4.1.0 之后,有一个新的方式可以让我们使用,就是将传进来的变量全部都存在数组中。以第一个例子而言,我们以 POST 的方式从窗体传来变量 $username,新的取得变量方式是:$_POST["username"],也就是说所有以 POST 传递过来的变量全部存在 $_POST 这个数组中。详细说明请参考 http://www.php.net/release_4_1_0.php

在 4.2.0 之前,新旧二种方式都可以使用,但是在 4.2.0 之后,Default 只能使用新的方式来传递变量。所以如果你安装的了新 PHP 而发现无法使用旧的 PHP 程序,别惊讶。

如果您还是要以旧的方式来传递变量,请修改 php.ini,将原本的 register_globals = Off 改成下列这个样子,并移除开头的批注符号 ";":

; register_globals = Off
register_globals = On

post_max_size

当使用者从网页中使用 HTML FORM 以 POST method 送出数据时,最大的数据上限为何。默认值是 8 MB。

error_log = syslog

file_uploads

是否允许使用者以 HTTP 上传档案。预设为 On。

file_uploads = On

upload_max_filesize

当使用者从网页中使用 PHP 上传档案时,档案最大的大小为何。预设是 2 MB。

upload_max_filesize = 2M

13.5 Apache 服务器状态与管理

身为系统管理者,必须时常查看系统状态,检查、注意主机是否有异常的情形发生。Apache 提供了详细的系统记录文件,我们可以经由这些档案了解服务器、网页是否有异常的情形。另外,Apache 也提供了一些工具,可以让我们了解服务器的运作情形。

13.5.1 Apache 状态信息

在安装完 Apache 后,如果您所管理的是一个大型的网页服务器,您一定会需要了解服务器的系统负荷是否足以处理庞大的网络流量。Apache 内建了 server-status 及 server-info 二种观看服务器信息的方法。

server-status 服务器状态信息

server-status 可以让我们了解 Apache 目前运作的情形,包括占用的系统资源、目前联机数量等。在使用 server-status 之前,我们必须先修改 httpd.conf,以打开此功能。

...
LoadModule status_module libexec/apache2/mod_status.so
...
#
# ExtendedStatus controls whether Apache will generate "full" status
# information (ExtendedStatus On) or just basic information (ExtendedStatus
# Off) when the "server-status" handler is called. The default is Off.
#
ExtendedStatus On
...
#
# Allow server status reports generated by mod_status,
# with the URL of http://servername/server-status
# Change the ".example.com" to match your domain to enable.
#
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 192.168.0.
</Location>
...

首先要确认的是 Apache 有载入 mod_status.so 这个模块,接着我们将 ExtendedStatus 设为 On,以显示详细的服务器状态。最后是找到 server-status 的区段,并移除开头的 #。在 server-status 区段中,我们设定了 Deny、Allow,以限制只有从某个地方联机进来的使用者可以查看服务器状态。在上述的范例中,我们限制只有从 192.168.0.x 的使用者才可以看到 server-status。

修改完 httpd.conf 后,我们必须使用下列指令重新启动 Apache:

# /usr/local/etc/rc.d/apache2.sh restart

接下来,我们就可以使用浏览器连到 http://192.168.0.1/server-status。请将 192.168.0.1 改成您的主机 IP。连到 server-status 后,您可以看到下列画面:

图 13-2

server-status 的输出中每个字段所代表的意义如下:

字段说明
Server VersionApache 服务器的版本。
Server BuiltApache 服务器编译安装的时间。
Current Time目前的系统时间。
Restart TimeApache 重新启动的时间。
Parent Server GenerationApache 父程序 (parent process) 的世代编号,就是 httpd 接收到 SIGHUP 而重新启动的次数。
Server uptimeApache 启动后到现在经过的时间。
Total accesses到目前为此 Apache 接收的联机数量及传输的数据量。
CPU Usage目前 CPU 的使用情形。
_SWSS....所有 Apache process 目前的状态。每一个字符表示一个程序,最多可以显示 256 个程序的状态。
Scoreboard Key上述状态的说明。以下为每一个字符符号所表示的意义:
  • _:等待连结中。
  • S:启动中。
  • R: 正在读取要求。
  • W:正在送出回应。
  • K:处于保持联机的状态。
  • D:正在查找 DNS。
  • C:正在关闭连结。
  • L:正在写入记录文件。
  • G:进入正常结束程序中。
  • I:处理闲置。
  • .:尚无此程序。
Srv本程序与其父程序的世代编号。
PID本程序的 process id。
Acc分别表示本次联机、本程序所处理的存取次数。
M该程序目前的状态。
CPU该程序所耗用的 CPU 资源。
SS距离上次处理要求的时间。
Req最后一次处理要求所耗费的时间,以千分之一秒为单位。
Conn本次联机所传送的数据量。
Child由该子程序所传送的数据量。
Slot由该 Slot 所传送的数据量。
Client客户端的地址。
VHost属于哪一个虚拟主机或本主机的 IP。
Request联机所提出的要求信息。

我们在查看 server-status 时,可以在输入的网址中加上参数 refresh 来让网页自动更新。例如,您可以输入 http://192.168.0.1/server-status?refresh=5,让网页每 5 秒钟自动重新加载。

server-info 服务器组态信息

server-info 和 server-status 的设定类似,我们可以经由 server-info 知道 Apache 的组态信息,包括版本、加载的模块等。

同样的,在使用 server-info 之前,我们必须先修改 httpd.conf,以打开此功能。

...
LoadModule info_module libexec/apache2/mod_info.so
...
#
# Allow remote server configuration reports, with the URL of
# http://servername/server-info (requires that mod_info.c be loaded).
# Change the ".example.com" to match your domain to enable.
#
<Location /server-info>
    SetHandler server-info
    Order deny,allow
    Deny from all
    Allow from 192.168.0.
</Location>
...

server-info 所使用的模块是 mod_info.so,我们先要确认的是 Apache 有该模块。接着我们找到 server-info 的区段,并移除开头的 #。在 server-info 区段中,我们一样设定了 Deny、Allow,以限制只有从某个地方联机进来的使用者可以查看服务器组态设定。

修改完 httpd.conf 后,我们必须使用下列指令重新启动 Apache 才可以使用:

# /usr/local/etc/rc.d/apache2.sh restart

最后您就可以使用 http://192.168.0.1/server-info 连到 Apache 的服务器组态信息页面:

图 13-3

在 server-info 中,我们可以看到最上方是 Apache 所有己加载的模块信息,接着是 Apache 主要的设定状态,而最下方是目前 Apache 设定文件和默认值不同的地方。在本页面的其它部份为每一个已加载的模块状态供您参考。

13.5.2 效能测试

Apache 提供了一个测试 Apache 效能的工具 - ab。你可以使用 ab 针对某个 URL 来模拟出连续的联机请求 (不限本地主机),并设定同时间要模拟多少联机。

以下为 ab 这个指令比较常用的参数说明:

参数 说明
-n requests 要做多少次联机请求,requests 为次数。
-c concurrency 同时有多少个联机,concurrency 为个数。
-t timelimit 最多等待回应的秒数。
-p postfile 要以 POST 方法联机所欲送出的参数档案。postfile 为存放参数的文件名称。

例如,我要对自己的机器中的 index.php 作测试,模拟 1000 次请求,每次最多同时 20 个联机,只要在命令列执行指令:

# /usr/local/sbin/ab -n 1000 -c 20 http://127.0.0.1/index.php

等了几秒之后出现:

This is ApacheBench, Version 2.0.41-dev <$Revision: 1.121.2.12 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient).....done
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests


Server Software: Apache/2.0.54
Server Hostname: 192.168.0.4
Server Port: 80

Document Path: /index.php
Document Length: 3803 bytes

Concurrency Level: 20
Time taken for tests: 9.543791 seconds
Complete requests: 1000
Failed requests: 1002
(Connect: 0, Length: 1002, Exceptions: 0)
Write errors: 0
Total transferred: 6286345 bytes
HTML transferred: 6124788 bytes
Requests per second: 104.78 [#/sec] (mean)
Time per request: 190.876 [ms] (mean)
Time per request: 9.544 [ms] (mean, across all concurrent requests)
Transfer rate: 643.25 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 3 62 106.7 28 771
Processing: 13 125 163.3 55 860
Waiting: 5 89 120.1 46 786
Total: 26 187 229.5 94 1558

Percentage of the requests served within a certain time (ms)
50% 94
66% 168
75% 198
80% 218
90% 488
95% 772
98% 898
99% 950
100% 1558 (longest request)

您可以增加最多同时联机数目及联机次数,操看看你机器的上限在哪里。

还有更多的参数,详细用法请 man ab

13.5.3 维护服务器记录文件

查看服务器记录文件可以让我们了解服务器的运作情形。Apache 预设会有二个记录文件,一个是所有联机的记录,预设的名称是 /var/log/httpd-access.log; 另一个是联机错误记录文件,预设的位置是 /var/log/httpd-error.log。记录文件的位置及文件名是由 httpd.conf 决定,如果您修改过记录文件的设定,则路径可能就不太一定。以下为 httpd.conf 关于记录文件的设定:

...
ErrorLog /var/log/httpd-error.log
...
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
...
CustomLog /var/log/httpd-access.log combined
...

我们来看一下 httpd-access.log 的内容:

图 13-4

我们截取一条记录加以说明。第一行开头的部份是客户端的 IP,接下来是联机的时间、所查看的网页、及所使用的操作系统、浏览器等。在存取记录中要显示什么信息是由 httpd.conf 中的 LogFormat 所控制。因为我们设定了 CustomLog 所使用的格式是 combined,而 combined 在 LogFormat 中的设定就是显示上述格式。LogFormat 的格式中,每一个字段使用都可以用 %X 表示,例如 %h 表示客户端的 IP。

基本上我们比较少直接查看 access log,我们会使用一些外挂软件来析记录文件。例如,统计每个网页的使用量、哪一个网页最常被存取、每天有多少联机等等。下一章中,我们会介绍如何安装使用网页分析软件。

我们可能比较常看的是错误记录文件。经由查看错误记录文件,我们可以知道网页中没有有连结是坏的、使用者有没有尝试连到一个不存在的网页。我们选三条错误记录来说明:

[Fri Dec 10 19:45:45 2004] [error] [client 163.30.0.2]
File does not exist: /home/www/style.css
[Fri Dec 10 20:55:44 2004] [error] [client 220.165.54.39]
request failed: URI too long
[Fri Dec 10 20:56:09 2004] [error] [client 220.165.54.39]
File does not exist: /home/www/c/winnt/system32/cmd.exe

第一个错误记录是有人要存取 style.css,但却找不到该档案,这可能是我们网页的 HTML 中有错误的连结。第二、三条记录看来应该是 Windows 的病毒,它试着去存取 system32/cmd.exe,想要找 Windows 网页服务器的漏洞。您可以在错误记录文件中看到很多这种病毒的讯息,很庆幸我们是使用 FreeBSD + Apache,不需要担心病毒的入侵。

随着使用人数的增加,网站的 log 档可能会越来越大,我们可以使用 FreeBSD 的 newsyslog 来把旧的 log 备份起来。在 newsyslog 中,我们可以指定要备份多少个 log 档,超过之后会自动删除最旧的档案。

首先编辑 /etc/newsyslog.conf 加入下列二行:

/var/log/httpd-access.log 644  7   *  $W0D1  J  /var/run/httpd.pid
/var/log/httpd-error.log  644  7   *  $W0D2  J  /var/run/httpd.pid

以上二行的意义是将 /var/log/httpd-access.log 这个档案做备份,备份后的文件名称像这样 httpd-access.log.0.bz2 。备份后该档案的权限是 644,最大的数字到 7,也就是最多八个档案,不限制档案多大时要备份,选在每周日半夜 1 点时备份,并将该档以 bzip2 压缩。在备份完后,要将 /var/run/httpd.pid 所记录的 Process ID 重新启动。