这是 Apache httpd 2.4。
我正在尝试将旧版安装从 2.2 移植到 2.4,并在此过程中对其进行一些清理。有很多具有相同设置的目录,其中散布着一些不同的目录。本质上,它看起来像这样:
<directory /var/www/aaa >
# lots of stuff
</directory>
<directory /var/www/bbb >
# lots of stuff
</directory>
<directory /var/www/ >
# lots of stuff
</directory>
<directory /var/www/ccc >
# lots of other stuff
</directory>
我希望避免多余的行,所以我希望有某种速记,例如:
<directory /var/www/aaa >
<directory /var/www/bbb >
<directory /var/www/ >
# lots of stuff
</directory>
<directory /var/www/ccc >
# lots of other stuff
</directory>
但<Directory>
不以我能找到的任何方式支持多个目录。所以<DirectoryMatch>
看起来很合适,像这样:
<directoryMatch /var/www/(aaa|bbb|) >
# lots of stuff
</directory>
<directoryMatch /var/www/ccc >
# lots of other stuff
</directory>
这会失败,因为/var/www/(aaa|bbb|)
匹配/var/www/ccc
不完整。与 相反<Directory>
,<DirectoryMatch>
不按照最短目录组件到最长的顺序进行处理。该手册声称“在每个组中,这些部分按照它们在配置文件中出现的顺序进行处理”,但即使我切换这些部分,结果仍然是相同的(即被“ ”而不是“ ”/var/www/ccc
击中) 。# lots of stuff
# lots of other stuff
在这个例子中,我当然可以扩展regexp( /var/www/(aaa|bbb|(?!ccc))
),但不幸的是,真正的配置比这复杂得多。使用正则表达式可能仍然是可能的,但结果将很难理解或维护。
那么,除了 DirectoryMatch 之外,是否还有其他方法可以做到这一点,有人可以给我提示吗?也许可以解释为什么 Apache 似乎更喜欢上面的部分匹配?谢谢。
答案1
没有一种易于阅读的方法来DirectoryMatch
匹配所有/var/www/aaa
, /var/www/bbb
, 和/var/www
, 但不是/var/www/ccc
。这是因为/var/www
包括所有其他三个目录。
可能更容易的是使用模组宏定义配置的公共部分,然后Directory
按照原始示例中的方式应用它们。
a2enmod macro # Enable the mod_macro module
systemctl restart apache2 # YMMV but this is the systemd way
然后您可以定义您的宏。这是我用的一个
# Logging
#
<Macro CronoLogger $vHost>
ServerSignature On
LogLevel warn
ErrorLog "|/usr/bin/cronolog /home/www/$vHost/logs/%Y/%m/%d/public-error.log"
CustomLog "|/usr/bin/cronolog /home/www/$vHost/logs/%Y/%m/%d/public-access.log" combined
</Macro>
我将它包含在这样的 vHost 定义中
Use CronoLogger www.contoso.com
在您的情况下,通过示例宏,StandardStuff param1 param2
您可以像这样使用它
<Directory /var/www>
Use StandardStuff /var/www /
</Directory>
<Directory /var/www/aaa>
Use StandardStuff /var/www /aaa
</Directory>
<Directory /var/www/bbb>
Use StandardStuff /var/www /bbb
</Directory>
<Directory /var/www/ccc>
# Do non-standard stuff here
#
</Directory>
答案2
该手册声称“在每个组中,这些部分按照它们在配置文件中出现的顺序进行处理”,但即使我切换这些部分,结果仍然是相同的(/var/www/ccc 被“#”击中)很多东西”而不是“#很多其他东西”)。
当两个指令匹配时,它们都会被处理。
启用mod_headers
( a2enmod headers
) 并尝试
<DirectoryMatch /var/www/(aaa|bbb|)>
Header add AAA one
</DirectoryMatch>
<DirectoryMatch /var/www/ccc>
Header add AAA two
</DirectoryMatch>
您将使用开发人员工具看到 的响应http://localhost/ccc
包含两个标头。
如果你想匹配/var/www
, /var/www/foo.html
, /var/www/aaa
/var/www/aaa/bar
, /var/www/bbb
, /var/www/bbb/baz
,那么这应该有效:
<DirectoryMatch ^/var/www/([^/]*|aaa/.*|bbb/.*)$>
[^/]*
匹配其中/var/www/
不是目录的任何内容aaa/.*|bbb/.*
匹配里面的任何内容,包括子目录$
这里很重要,否则正则表达式仅定义匹配目录的开头,并且超出您想要的范围
如果您只需要匹配目录(并且里面没有其他文件),请使用
<DirectoryMatch ^/var/www(/aaa|/bbb)?/?$>
我可能更喜欢LocationMatch
(如果可能的话),这样您就不必关心目录结构。