httpd命令和apachectl命令                        

[root@localhost ~]# httpd -h
Usage: httpd [-D name] [-d directory] [-f file]
[-C "directive"] [-c "directive"]
[-k start|restart|graceful|graceful-stop|stop]
[-v] [-V] [-h] [-l] [-L] [-t] [-T] [-S] [-X]
Options:
-D name : define a name for use in <IfDefine name> directives
-d directory : specify an alternate initial ServerRoot
-f file : specify an alternate ServerConfigFile
-C "directive" : process directive before reading config files
-c "directive" : process directive after reading config files
-e level : show startup errors of level (see LogLevel)
-E file : log startup errors to file
-v : show version number
-V : show compile settings
-h : list available command line options (this page)
-l : list compiled in modules
-L : list available configuration directives
-t -D DUMP_VHOSTS : show parsed vhost settings
-t -D DUMP_RUN_CFG : show parsed run settings
-S : a synonym for -t -D DUMP_VHOSTS -D DUMP_RUN_CFG
-t -D DUMP_MODULES : show all loaded modules
-M : a synonym for -t -D DUMP_MODULES
-t : run syntax check for config files
-T : start without DocumentRoot(s) check
-X : debug mode (only one worker, do not detach)

apachectl命令和httpd命令基本相同。httpd接受的选项,apachectl都接受。但apachectl还可以省略"-k"选项直接管理httpd进程。

apachectl [-k] start:按照默认路径,读取默认配置文件,并启动httpd。
apachectl [-k] stop:关闭httpd进程。
apachectl [-k] restart:重启httpd进程。
apachectl [-k] graceful-stop:graceful stop,表示让已运行的httpd进程不再接受新请求,并给他们足够的时间处理当前正在处理的事情,处理完成后才退出。所以在进程退出前,日志文件暂时不会关闭,正在进行的连接暂时不会断开。
apachectl [-k] graceful:graceful restart,即graceful-stop+start。
apachectl [-k] configtest:语法检查。
在systemd环境下,还可以使用apachectl status或systemctl status httpd查看httpd进程的详细信息。

配置文件规则和常见指令                      

httpd的核心体现在配置文件,各种功能都通过配置文件来实现。使用rpm包安装的httpd默认配置文件为/etc/httpd/conf/httpd.conf。可以使用httpd -f config_path指定要加载的配置文件。

配置文件中全是一些指令配置,每个指令都是某个模块提供的。以下是配置文件的一些规则:

  1. 指令生效方式是从上往下读取,这一点非常非常重要。很多指令的位置强烈建议不要改变,例如Include conf.d/*.conf指令建议不要移动位置。
  2. "#"开头的行为注释行,只能行头注释,不能行中注释。
  3. 对大小写不敏感,但是建议指令名称采用"驼峰式"命名。例如ServerRoot,DocumentRoot。
  4. 一行写不下的可以使用"\"续行,但是"\"后不能有任何字符,包括空格也不允许。
  5. 指令配置格式为"Directive value",例如"ServerRoot /etc/httpd",如果value中包含特殊字符或空格,则必须使用双引号包围。
  6. 由于可以通过Include指令包含其他配置文件,又支持各种路径的容器,所以在httpd启动时会先进行配置文件的合并。理解合并规则非常重要,具体见配置文件合并规则

Listen指令                            

设置监听套接字。设置方式很简单,包括以下几种情况:

# 监听两个端口
Listen
Listen # 监听套接字绑定在给定地址和端口上
Listen 192.170.2.1:
Listen 192.170.2.5:

ServerRoot指令                                      

该指令设置httpd的安装位置,也就是常称之为的basedir,在此目录下应该具有module、logs等目录。rpm安装的httpd的ServerRoot默认为/etc/httpd,编译安装的ServerRoot路径由"--prefix"选项指定,例如/usr/local/apache。

[root@localhost ~]# ls /etc/httpd/ -l
总用量
drwxr-xr-x. root root 12月 : conf
drwxr-xr-x. root root 12月 : conf.d
drwxr-xr-x. root root 12月 : conf.modules.d
lrwxrwxrwx. root root 12月 : logs -> ../../var/log/httpd
lrwxrwxrwx. root root 12月 : modules -> ../../usr/lib64/httpd/modules
lrwxrwxrwx. root root 12月 : run -> /run/httpd

这个指令很关键,安装好apache后一般不会去做任何修改,因为很多指令的路径以及相对路径都是基于此路径的。严格地说,除了网络路径,基本上所有本地文件系统类的路径只要不是绝对路径,相对路径都基于此路径展开

例如,当指定"ServerRoot /usr/local/apache"时,下面几个指令中描述的本地路径,等号前面的采用的都是相对路径,等号右边的都是他们等价的绝对路径写法。

DocumentRoot "htdocs"                    = DocumentRoot "/usr/local/apache/htdocs"
LoadModule dir_module modules/mod_dir.so = LoadModule dir_module /usr/local/apache/modules/mod_dir.so
ErrorLog "logs/error_log" = ErrorLog /usr/local/apache/logs/error_log
Alias /net_path local_fs_path = Alias /net_path /usr/local/apache/local_fs_path
Include conf.d/vhost.conf = Include /usr/local/apache/conf.d/vhost.conf

但注意,容器< Directory PATH >的PATH一般设置为文件系统的绝对路径,因为它是路径匹配性质的。但它仍可以使用相对路径时,此时它相对的是根文件系统的"/",而非ServerRoot。

所以,这个指令强烈不建议做任何修改,修改是很简单,但是牵一发而动全身。

DocumentRoot指令                                    

如果说,ServerRoot是httpd中本地文件相对路径的根,那么DocumentRoot就是网络路径相对路径的根。顾名思义,DocumentRoot是文档的根目录,这个文档的意思是展现在网络上的文档。使用rpm包安装的httpd的DocumentRoot默认值为"/var/www",编译安装的httpd,其DocumentRoot默认为"PREFIX/htdocs",也就是"$ServerRoot/htdocs"。

设置DocumentRoot后,将需要在网络上访问的文件都放进此目录下即可。

例如,假设httpd所在主机IP为192.168.100.,DocumentRoot使用默认的/usr/local/apache/htdocs,那么下面几个URL中,左边的是浏览器中输入的值,右边的是其访问的服务器上的资源路径。
http://192.168.100.14/index.html         ==> /usr/local/apache/htdocs/index.html
http://192.168.100.14/index.php ==> /usr/local/apache/htdocs/index.php
http://192.168.100.14/subdir/index.html ==> /usr/local/apache/htdocs/subdir/index.html
http://192.168.100.14/subdir/index.php ==> /usr/local/apache/htdocs/subdir/php

也就是说,DocumentRoot的值对应的是http://192.168.100.14/的"/"。

DirectoryIndex指令                                

该指令设置的是"当搜索的URL中的路径使用了"/"结尾时,httpd将搜索该指令所指定的文件响应给客户端"。也就是说,当url表示搜索的是目录时,将查找该目录下的DirectoryIndex。注意,很多时候如果没有给定尾部的"/",httpd的dir_module模块会自行加上"/",当然,是否补齐尾随的"/",也是可以控制的,见DirectorySlash指令。

DirectoryIndex的设置格式为:

DirectoryIndex disabled | local-url [local-url]

例如,当设置"DirectoryIndex index.html"时,如果在浏览器中输入下面左边的几个URL,httpd将响应右边对应的文件。

http://192.168.100.14           ==> $DocumentRoot/index.html
http://192.168.100.14/newdir/ ==> $DocumentRoot/newdir/index.html

可以指定多个index文件,它们将按顺序从左向右依次查找,并返回第一个找到的index文件。例如:

<IfModule dir_module>
DirectoryIndex index.php index.html /mydir/index.html
</IfModule>

当浏览器中输入http://192.168.100.14/时,将首先搜索index.php,如果该文件不存在,则再搜索index.html,如果还找不到,则再找该目录的子目录下的文件/mydir/index.html。但这不表示http://192.168.100.14/mydir/会搜索/mydir/index.html。

可以使用多个DirectoryIndex指令进行追加设置,它等价于单行设置多个值,例如下面的设置等价于DirectoryIndex index.php index.html

DirecotryIndex index.php
DirectoryIndex index.html

如果要替换某个值,则直接修改或使用disabled关键字禁用其前面的Directoryindex。例如禁用index.php,只提供index.html的索引。

DirectoryIndex index.php
DirectoryIndex disabled
DirectoryIndex index.html

但注意,"disabled"关键字必须独自占用一个DirectoryIndex指令,否则它将被解析成字面意思,也就是说将其当作一个index文件响应给客户端。

DirectoryIndex指令可以设置在Server、Virtual host、Location和Directory上下文。所以,当设置在location或Directory容器中时,它将覆盖全局设置。例如,当DocumentRoot为/usr/local/apache/htdocs时:

DirectoryIndex index.php
<directory /usr/local/apache/htdocs/newdir>
DirectoryIndex index.html
</directory>
# 或者
<location /newdir>
DirectoryIndex index.html
</location>

在输入http://IP/newdir/时,将提供index.html而非index.php。

当DirectoryIndex提供的索引文件都不存在时,将根据Options中的Indexes选项设置决定是否列出文件列表,除非是提供文件下载,否则出于安全考虑,这个选项是强烈建议关闭的。例如以下设置为打开,当

<directory /usr/local/apache/htdocs/newdir>
Options Indexes
DirectoryIndex index.html
</directory>

ServerName和ServerAlias                          

ServerName用于唯一标识提供web服务的主机名,只有在基于名称的虚拟主机中该指令才是必须提供的。也就是说,如果不是在基于名称的虚拟主机中,可以任意指定该指令的值,只要你认为它能唯一标识你的主机。但如果不设置该指令,那么httpd在启动时,将会反解操作系统的IP地址。

唯一标识主机的方式,也即ServerName的语法为:

ServerName {domain-name|ip-address}[:port]

例如,在主机web.longshuai.com上提供了一个httpd web服务,如果还想使用www.longshuai.com提供同样的服务,还想效率更高点,则在设置DNS别名后再配置:

serverName www.longshuai.com

ServerAlias用于定义ServerName的别名。如果在定义ServerName之后再定义ServerAlias,那么ServerName和ServerAlias没有任何区别。当然,为了区分基于名称的虚拟主机,还是必须要定义ServerName。

例如,下面几个ServerName和ServerAlias是完全等价的。

<VirtualHost *:>
ServerName server.example.com
ServerAlias server server2.example.com server2
ServerAlias *.example.com
# ...
</VirtualHost>

Include指令                              

在httpd启动时,首先会解析配置文件。httpd支持include指令来包含其他文件,在解析配置文件时会进行配置合并。

支持通配符"*"、"?"和"[]",但它们不能匹配斜线"/",如有必要,它们会按照文件名的字母顺序依次进行加载。如果include指令中指定包含一个目录,则会按照字母顺序加载该目录内的所有文件,这比较容易出错,因为有些时候会产生一些临时文件或非配置类的文件。

例如:

Include /usr/local/apache/conf/ssl.conf
Include /usr/local/apache/conf/vhosts/*.conf

可以使用绝对路径,也可以使用相对路径,如果使用相对路径,则它相对于ServerRoot。

Include conf/ssl.conf
Include conf/vhosts/*.conf

Define和UnDefine指令                                  

该指令用于定义参数或定义向后全局生效的变量。语法格式为:

Define param [value]

当只给定一个param时,表示定义一个参数,这个参数用于< IfDefine param >容器进行判断,只有定义了的参数param,该容器才返回真,其内封装的指令才生效。它的等价行为是在httpd启动时(必须是启动时),使用"-D"选项定义参数。例如下面两个方法是等价的:

# startup command
shell> httpd -DMyName ......
# in config
Define MyName

当给定了两个参数,即还指定了value时,将表示定义一个变量,该变量具有向后全局性。也就是说,定义在某个虚拟主机中的变量在后面的另一个虚拟主机中也有效。引用变量时,使用${var}的方式。注意,变量名中不能包含冒号":"。

例如:

<IfDefine !TEST>
Define servername www.example.com
</IfDefine> DocumentRoot "/var/www/${servername}/htdocs"

使用UnDefine指令则是取消Define定义的参数或变量。语法为UnDefine param

VirtualHost指令                                    

无疑,这是最重要的指令之一。用于封装一组指令只作用于指定主机名或IP地址的虚拟主机上。

语法格式为:

<VirtualHost addr[:port] [addr[:port]] ...> ... </VirtualHost>

其中addr部分可以是以下几种情况:

  • 虚拟主机的IP地址
  • 虚拟主机IP地址对应的FQDN(不推荐)
  • 字符"*",匹配任意IP地址
  • 字符串"_default_",是"*"的别名

例如:

<VirtualHost 10.1.2.3:>
ServerAdmin webmaster@host.example.com
DocumentRoot "/www/docs/host.example.com"
ServerName host.example.com
ErrorLog "logs/host.example.com-error_log"
TransferLog "logs/host.example.com-access_log"
</VirtualHost>

需要为虚拟主机指定ServerName,否则它将会从主配置继承。对于基于名称的虚拟主机,ServerName更是不可缺少,否则将继承操作系统的FQDN。

当一个请求到达时,将按照最佳匹配进行主机匹配:通配的内容越少,优先级越高,也就越佳。例如"192.168.100.14:80"的优先级高于"*:80"。如果基于名称的虚拟主机无法匹配上,则采用虚拟主机列表中的第一个虚拟主机作为响应主机。如果所有虚拟主机都无法匹配上,则采用从主配置段落中的主机,如果主配置段落中注释了DocumentRoot,则返回对应的错误。

具体配置方法,见配置httpd虚拟主机

Options和AllowOverride指令                              

Options启用或禁用指定目录下的某些特性。有效值包括:All、None、ExecCGI、FollowSymLinks、Includes、IncludesNOEXEC、Indexes、MultiViews、SymLinksIfOwnerMatch。

不指定options时,默认为all。一般除了提供下载服务会开启一个Indexes选项,其他选项都会关掉,即使用:

Options None

AllowOverride指令用于控制是否读取".htaccess"配置文件。

如何设置这个指令要看具体情况,有以下几种值,此外还可以设置为all和none,表示启用、禁用所有特性。

  • AuthConfig:基于用户认证时设置该值,此时将可以使用AuthGroupFile, AuthName, AuthType, AuthUserFile, equire等认证相关指令。
  • FileInfo: 控制文档类型时使用该值,此时将可以使用ErrorDocument, SetHandler,以及一些URL重写的指令。
  • Indexes:控制目录索引时使用该值,此时可以使用AddIcon, DirectoryIndex。
  • Limit:是否允许使用order、allow、deny指令,这三个指令已经废弃,目前还存在是为了兼容老版本。

例如下面的指令使得在使用非认证类和索引控制类指令时,将产生服务器类的错误。

AllowOverride AuthConfig Indexes

Require指令                              

该指令只能放在Directory容器中,用于控制对目录的访问权限。它的主要功能是由mod_authz_core模块提供,但有些身份认证类模块也提供它额外的功能,这时它可以放在< Directory >、< Files >或< Location >容器中。

主要功能:

  • Require all granted
    无条件允许所有人访问该目录
  • Require all denied
    无条件拒绝所有人访问该目录
  • Require env env-var [env-var] ...
    只有给定的环境变量var-env已经定义才允许访问该目录
  • Require method http-method [http-method] ...
    只有给定的HTTP请求方法才允许访问该目录,如只允许GET才能访问
  • Require expr expression
    只有给定的表达式为true才允许访问该目录

身份认证类模块提供的require指令功能包括:

  • mod_authz_user为require指令提供的功能:

    • Require user userid [userid] ...:认证列表中只有指定的userid才能访问
    • Require valid-user:认证列表中的所有用户都可以访问
  • mod_authz_groupfile为require指令提供的功能:
    • Require group group1 [group2] ...:指定组内的用户都可以访问
  • 本地文件系统身份参考类:
    • Require file-owner:要求web用户名必须和请求文件的uid对应的username完全相同
    • Require file-group:要求web用户名必须为请求文件的gid组中的一员
  • mod_authz_host为require指令提供的ip和host功能:
    • Require ip 192.168.1.104 192.168.1.205
    • Require ip 10.1
    • Require ip 10 172.20 192.168.2
    • Require ip 10.1.0.0/255.255.0.0
    • Require ip 10.1.0.0/16
    • Require host www.example.org
    • Require host example.org
    • Require host .net example.edu
    • Require local

可以在require指令后紧跟not关键字,表示取反。例如"require not group group1"、"require not local"等。

还支持require条件容器,包括< RequireAll >、< RequireAny >和< RequireNone >,当require指令没有写在任何Require容器中时,它们隐式包含在一个< RequireAny >容器中。

    • < RequireAll >:其内封装的Require指令必须全都不能失败,且至少有一个成功时,该容器成功。如果其内所有指令既不成功又不失败,则该容器中立。其余所有情况都会导致该容器失败。
    • < RequireAny >:其内封装的Require指令只要有一个成功,该容器就成功。如果其内所有指令既不成功又不失败,则该容器中立。其余所有情况(即全部失败时)都会导致该容器失败。
    • < RequireNone >:其内封装的Require指令只要有一个成功时该容器就失败,否则就中立。

长连接相关指令                                

KeepAlive指令用于开启和关闭长连接功能。

KeepAlive on/off

在没有开启长连接时,客户端每请求一个资源都需重新建立一次TCP连接,而使用了长连接后,客户端只需在最初请求一次TCP连接,之后就可以使用同一个TCP连接发送其他的http请求。长连接的状态是指在服务端处理完某一个请求后,它立即进入长连接状态以保持TCP连接不断开,等待客户端再次发送请求。

但长连接自身的缺陷是会一直占用着连接不释放,所以必须得给出一个长连接的超时时间。这个超时时间由KeepAliveTimeout指令控制,进入长连接后如果在此时间间隔内客户端还没有发送新请求,则TCP连接自动断开。如果在长连接状态下,客户端再次发送了请求,则服务端处理请求,并在处理完请求后又再次进入长连接状态并计算KeepAliveTimeout。

此外,还可以通过指令MaxKeepAliveRequests控制每个长连接下的TCP连接的能接受的最大请求数。无疑,这个值应该设置的大一些,设置为0表示无限制。这个指令是从数量的角度控制长连接的TCP应该何时断开。例如,在长连接超时时间内接受同一个客户端的500个请求才断开,然后该客户端再有新的请求只能重新建立TCP连接。

MaxKeepAliveRequests 

容器类指令                            

路径和条件判断容器包括:

  • < Directory >、< DirectoryMatch >
  • < Files >、< FilesMatch >
  • < Location >、< LocationMatch >
  • < IfModule >
  • < IfDefine >
  • < IfVersion >
  • < if >
  • < elseif >
  • < else >

容器< Directory >和< Files >                              

还包括它们的正则匹配容器< DirectoryMatch >、< FilesMatch >。

< Directory >容器的作用是"对于匹配到的目录,封装一组指令,这些指令只作用于该目录以及它的子目录中的文件"。注意,< Directory >容器通常都是用绝对路径,即< Directory /PATH/to/DIR >,如果使用相对路径,则它相对于根文件系统的"/"。例如< directory newdir >等价于< directory /newdir >。

<Directory "/">
AllowOverride none
require all denied
</Directory> <Directory "/usr/local/apache/htdocs">
require all granted
</Directory>

第一个容器表示拒绝所有对"/"下内容的访问,包括子目录中的文件,这个根是根文件系统的根,而不是ServerRoot。而第二个容器则表示允许/usr/local/apache/htdocs目录下文件的访问。

由此可以想象得出,出于安全考虑,应该总是先将父目录进行限制,再在需要放宽权限的子目录中指定特定的权限。正如上面的设置,将最顶级目录"/"完全限制,然后在小范围的htdocs目录中放行。

再看< Files >容器,它针对的是某个或某些特定的能被匹配上的文件。它匹配的范围是它所在的上下文。

例如,下面的指令如果写在server上下文,那么将对任意private.html文件拒绝。

<Files private.html>
require all denied
</Files>

而如果将其写在< directory >容器中,则只对该目录容器中的所有private.html生效。由于< directory >会递归到子目录中,所以子目录中的private.html也会拒绝,但非private.html将被允许。

<Directory "/usr/local/apache/htdocs">
require all granted
<Files private.html>
require all denied
</Files>
</Directory>

< directory >和< files >容器可以使用通配符,"*"表示任意字符,"?"表示任意单个字符,"[]"表示范围,如[a-z]、[0-9],但是这些通配符都不能匹配"/"。所以要跨目录匹配时,必须显式指定各个目录的"/"符号。

例如,<directory /*/public.html>无法匹配/home/user/public.html,但directory /home/*/public.html可以匹配。

它还可以使用正则表达式匹配,只需使用一个"~"符号即可。这时和使用< DirectoryMatch >、< FilesMatch >是一样的,只不过Match类指令不需要使用"~"符号。

例如,下面的设置。其中后两个Directory容器是等价的。

# 匹配不区分大小写的gif/jpg/jpeg/png
<FilesMatch "\.(?i:gif|jpe?g|png)$">
Require all denied
</FilesMatch> <Directory ~ "^/usr/local/apache/htdocs/[0-9]{3}">
DirectoryIndex digest.html
</Directory> <DirectoryMatch "^/usr/local/apache/htdocs/[0-9]{3}">
DirectoryIndex digest.html
</DirectoryMatch>

需要注意的是,httpd采用的pcre库提供的perl兼容正则。以下是官方手册提供的一个示例,使用的命名捕获语法,它将匹配/var/www/combined/目录下的一级子目录,但不进行递归。将每个匹配到的结果保存到命名的分组sitename中,并通过环境变量"MATCH_capturename"进行引用,其中capturename必须转为大写字母,因为它就是这样赋值的。

<DirectoryMatch "^/var/www/combined/(?<sitename>[^/]+)">
Require ldap-group cn=%{env:MATCH_SITENAME},ou=combined,o=Example
</DirectoryMatch>

目前已经不能使用未命名的后向引用,例如$0,$1...。在URL重写时,正则语法至关重要,像grep/sed/awk中天然支持的基础正则和扩展正则语法虽然能解决大部分问题,但想要实现复杂的需求,只能使用语义丰富、完整的正则,如pcre提供的正则。

容器< Location >                                

该容器和< Directory >、< Files >容器差不多,都是对满足匹配条件的路径封装一组指令,这些指令只生效于这些能匹配的路径。但是< Location >和< Directory >、< Files >最大的区别是:前者匹配的目标是WebSpace,即匹配URL中的路径,而后两者匹配的是本地文件系统的路径。

例如,当设置下面的location容器时,将匹配http://192.168.100.14/newdir/index.html

<Location "/newdir">
......
</Location>

location支持三种匹配模式:

  • 精确匹配:location的模式和URL中的路径部分精确对应。
  • 加尾随斜线:location的模式中加了尾随斜线时,将匹配该目录里面的内容。
  • 无尾随斜线:location的模式中没有尾随斜线时,将匹配该目录和目录里面的内容。

例如,下面两个容器,第一个将匹配/private1、/private1/和/private1/file.txt,但不能匹配/private1other,而第二个将匹配/private2/和/private2/file.txt,但不能匹配/private2和/private2other。

<Location "/private1">
......
</Location> <Location "/private2/">
......
</Location>

location和sethandler指令一起使用时很方便。例如,开启状态信息页面:

<Location "/server-status">
SetHandler server-status
Require all granted
</Location>

同样,除了支持"*"、"?"、"[]"的通配符匹配,还支持"~"和LocationMatch指令的正则匹配。方法见上面的< Directory >容器。

< IfDefine >、< IfModule >和< IfVersion >条件判断                        

这三个容器都是条件判断容器,且都只在httpd启动时进行判断,判断为真,则封装在其内的指令生效,否则忽略。且都可以在条件前加一个"!"以实现条件的否定,而且都可以嵌套以实现更复杂的配置。

< IfModule >容器是指当启动时加载了某模块时,该容器内的指令生效。可以是静态加载的模块,或者使用LoadModule指令加载的,但如果这样的话,加载对应模块的LoadModule指令必须在< IfModule >指令之前。例如:

LoadModule status_module modules/mod_status.so

<IfModule "status_module">
<Location "/server-status">
SetHandler server-status
Require all granted
</Location>
</IfModule>

< IfDefine param >容器用于判断参数param是否已经定义,如果定义了,则条件为真,封装在其内的指令生效,否则忽略。加上感叹号则表示取反,例如< IfDefine !param >。

那么如何定义参数呢?有两种方法:使用httpd命令的"-D"选项;使用Define指令。

例如,在使用httpd启动时,加上一个"-D"选项定义MyName参数。

httpd -DMyName ......

或者在配置文件中使用Define指令进行定义,但必须在< IfDefine >容器之前定义。例如:

httpd -DReverseProxy -DUseCache -DMemCache ...

<IfDefine ReverseProxy>
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<IfDefine UseCache>
LoadModule cache_module modules/mod_cache.so
<IfDefine MemCache>
LoadModule mem_cache_module modules/mod_mem_cache.so
</IfDefine>
<IfDefine !MemCache>
LoadModule cache_disk_module modules/mod_cache_disk.so
</IfDefine>
</IfDefine>
</IfDefine>

< IfVersion >容器用于判断httpd的版本。例如:

<IfVersion >= 2.4>
# this happens only in versions greater or equal 2.4..
</IfVersion>

< If >、< ElseIf >和< Else >容器                        

意义不言自明。< If >...< /If >判断表达式是否为真,如果为真,则封装在其内的指令生效;< ElseIf >...< /ElseIf >作用于< If >...< /If >之后,而< Else >...< /Else >则作用于最后。

表达式的写法和shell脚本的表达式差不多,例如数值比较"-eq"、"-gt",字符串比较"=="、">=",以及其他一些表达式"-z"、"-n"、"-f"等,此外,它还支持正则匹配表达式"~="、"!~"。具体相关函数、变量、表达式、语法等见 http://httpd.apache.org/docs/2.4/expr.html

# 请求首部没有Host字段时,该段指令将生效。
<If "-z req('Host')">
...
</If> # 如果请求主机地址属于0/,则if段生效,否则如果属于0/,则elseif段生效,否则else生效
<If "-R '10.1.0.0/16'">
#...
</If>
<ElseIf "-R '10.0.0.0/8'">
#...
</ElseIf>
<Else>
#...
</Else>

配置文件的合并规则                              

配置文件的段落以一种非常特殊的顺序生效。理解配置文件的合并规则非常重要,否则配置了半天可能发现根本不会生效。

以下是5个组类合并的顺序:

  • 1.< Directory > (正则匹配的容器除外)
  • 2.< DirectoryMatch > (以及< Directory "~" >)
  • 3.< Files >和< FilesMatch >同时处理
  • 4.< Location >和< LocationMatch >同时处理
  • 5.< If >

此外,还需要注意的一些规则是:

  • 除了< Directory >容器,每个组以它们出现的顺序进行合并。例如一个/foo请求可以匹配< Location "/foo/bar" >和< Location "/foo" >,它们都属于上面列出的第4组,所以对于这两个Location容器,谁配置在前面就匹配谁。
  • < Directory >容器即上面的第一组处理的顺序是先处理路径"短"的,再处理路径长的。这里的短指的是离根文件系统的"/"越近就越短。由于这个组不包含正则匹配的表达式(即< Directory ~ >),所以这里的"短"就代表它的路径表达式短。例如< Directory "/var/web/dir" >将优先于< Directory "/var/web/dir/subdir" >被处理。
  • 如果出现多个< Directory >的路径完全一样的极端情况,那么将按照出现顺序处理。
  • 使用Include指令包含的文件将被插入到该指令的位置,然后按规则进行处理。
  • < VirtualHost >段落的配置将在外部对应的段处理完毕以后再处理,这样就允许虚拟主机覆盖主服务器的设置。
  • 当请求是由mod_proxy处理的时候,< Proxy >容器将会在处理顺序中取代< Directory >容器的位置。

需要注意的是,配置文件中的指令都是由各个模块提供的,所以各指令是由各对于模块来解析、处理、合并的,配置文件的作用只不过是将各个模块的指令整合在一起方便定义。另外,上面定义的5个组别都是由httpd的核心模块提供的,因此它们才有处理顺序的要求。

当在运行时进行请求匹配,将先按照上面合并规则提供的顺序进行匹配,如果某个组中出现了能成功匹配请求的模块,将提升一次合并的层次,使得这次模块的匹配变为第三次匹配。例如下面的配置使用了由mod_headers提供的Header指令用于设置HTTP的首部,如果请求/example/index.html,那么最终设置的CustomHeaderName首部的值是什么呢?

<Directory "/">
Header set CustomHeaderName one
<FilesMatch ".*">
Header set CustomHeaderName three
</FilesMatch>
</Directory> <Directory "/example">
Header set CustomHeaderName two
</Directory>

首先按照前面提供的合并顺序匹配到"/",这会初始化设置CustomHeaderName的值为one,再匹配到/example,CustomHeaderName被设置为two。最后分组中提供的指令FilesMatch匹配成功,提升一次合并的层次,这是第三次匹配,导致CustomHeaderName最终设置为three。

下面的例子中,如果这些指令都对请求生效,它们将按照"A > B > C > D > E"的顺序生效。

<Location "/">
E
</Location> <Files "f.html">
D
</Files> <VirtualHost *>
<Directory "/a/b">
B
</Directory>
</VirtualHost> <DirectoryMatch "^.*b$">
C
</DirectoryMatch> <Directory "/a/b">
A
</Directory>

D和E无疑是最后生效的。再看三个Directory类的容器,对于Directory和DirectoryMatch,前者先生效,所以C排在A和B后,对于A和B,虚拟主机会在外部段落处理完后再处理,所以在A和B进行合并时,B将覆盖A,也即A先生效。所以顺序为"A>B>C>D>E"。但如果将上面的A段落改为:

<Directory "/a/b">
A
<FilesMatch f.html>
D1
</Files>
</Directory>

那么最终的顺序为"A>B>C>D>D1>E"。

以下示例则更有教育意义。尽管Directory设置了更严格的权限,但因为Location比Directory更后生效,它对所有访问都不做任何限制。也就是说,Directory在这里的权限设置是完全多余的。所以说,理解配置文件的合并规则对写配置文件至关重要。

<Location "/">
Require all granted
</Location> # Whoops! This <Directory> section will have no effect
<Directory "/">
<RequireAll>
Require all granted
Require not host badguy.example.com
</RequireAll>
</Directory>

apache配置文件说明及一些指令的更多相关文章

  1. (原创)LAMP搭建之二:apache配置文件详解(中英文对照版)

    LAMP搭建之二:apache配置文件详解(中英文对照版) # This is the main Apache server configuration file. It contains the # ...

  2. Apache配置文件httpd.conf内容翻译

      本文已经废弃,现在apache2不依靠httpd.conf来配置. Ubuntu下默认的配置文件是/etc/apache2/sites-available/default 可以修改上面文件来修改a ...

  3. Apache配置文件相关命令

    转:http://www.365mini.com/page/apache-options-directive.htm Options指令是Apache配置文件中一个比较常见也比较重要的指令,Optio ...

  4. Apache配置文件服务器

    配置Apache文件服务器: apache配置文件服务器httpd.conf中这两个模块必须不被注释LoadModule autoindex_module modules/mod_autoindex. ...

  5. Apache配置文件中的deny和allow的使用

    Apache配置文件中的deny和allow的使用 由于产品的需要,最近在配置apache的负载均衡功能,但是在配置虚拟主机的访问权限的时候我们遇到了一些问题.主要问题是deny和allow的执行顺序 ...

  6. MAC下通过改apache配置文件切换php多版本的方法

    网上关于php版本切换的文章有很多,但测试发现有很多都不行,所以不如自己想办法实现了,所以下面这篇文章主要给大家介绍了在MAC系统下通过改apache配置文件的方法来使php多版本切换的相关资料,需要 ...

  7. Apache 配置文件详解

    0x01 禁止目录列表访问 () 备份httpd.conf配置文件,修改内容: <Directory "/web"> Options FollowSymLinks Al ...

  8. Linux服务器---apache配置文件

    Apache配置文件 Apache的配置文件默认路径是“/etc/httpd/conf/httpd.conf”,编辑该文件就可以修改Apache的配置 1.设置网页主目录,参数DocumentRoot ...

  9. apache配置文件详解与优化

    apache配置文件详解与优化 一.总结 一句话总结:结合apache配置文件中的英文说明和配置详解一起看 1.apache模块配置用的什么标签? IfModule 例如: <IfModule ...

随机推荐

  1. WPF使用FlowDocument实现图文混排

    代码: <RichTextBox CaretBrush="#fff" Background="Transparent" BorderThickness=& ...

  2. Asp.net Core3.0 跨域配置

    原文:http://www.zilaohu.cn/Jie/Detail_Jie?ID=78840a04-55b8-4988-80b2-f964fd822d63 下面配置后:被拒绝的域请求后,可以进入方 ...

  3. netty解决粘包半包问题

    前言:开发者用到TCP/IP交互时,偶尔会遇到粘包或者半包的数据,这种情况有时会对我们的程序造成严重的影响,netty框架为解决这种问题提供了若干框架 1. LineBasedFrameDecoder ...

  4. docker可视化工具Portainer部署与汉化

    为了更好的观察Docker运行状态,我们采用Portainer工具进行可视化,下面是部署过程总结: 环境: Liunx:CentOS Linux release 7.6.1810 (Core) Doc ...

  5. 如何计算Data Guard环境中Redo所需的网络带宽传输 (Doc ID 736755.1)

    How To Calculate The Required Network Bandwidth Transfer Of Redo In Data Guard Environments (Doc ID ...

  6. socket简单介绍

    一 三种类型的套接字: 1.流式套接字(SOCKET_STREAM)     提供面向连接的可靠的数据传输服务.数据被看作是字节流,无长度限制.例如FTP协议就采用这种. 2.数据报式套接字(SOCK ...

  7. pycharm报错:Process finished with exit code -1073741819 (0xC0000005)解决办法

    这个是几个月前的问题了,有小伙伴在CSDN问我咋解决的,那我今天在这边把这个问题解决办法分享下吧,免得大家把很多时间都浪费在安装排坑上面,有些坑虽然解决了还真不知道啥原因. 我的pycharm一直用的 ...

  8. datatable的dom配置

    l - Length changing 改变每页显示多少条数据的控件 f - Filtering input 即时搜索框控件 t - The Table 表格本身 i - Information 表格 ...

  9. Softmax用于手写数字识别(Tensorflow实现)-个人理解

    softmax函数的作用   对于分类方面,softmax函数的作用是从样本值计算得到该样本属于各个类别的概率大小.例如手写数字识别,softmax模型从给定的手写体图片像素值得出这张图片为数字0~9 ...

  10. MATLAB聚类有效性评价指标(外部 成对度量)

    MATLAB聚类有效性评价指标(外部 成对度量) 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 更多内容,请看:MATLAB: Clustering ...