httpd配置文件規則說明和一些基本指令

来源:http://www.cnblogs.com/f-ck-need-u/archive/2017/10/08/7636836.html
-Advertisement-
Play Games

本文目錄:1.1 httpd命令和apachectl命令1.2 配置文件規則和常見指令 1.2.1 Listen指令 1.2.2 ServerRoot指令 1.2.3 DocumentRoot指令 1.2.4 DirectoryIndex指令 1.2.5 ServerName和ServerAlias ...


本文目錄:
1.1 httpd命令和apachectl命令
1.2 配置文件規則和常見指令
 1.2.1 Listen指令
 1.2.2 ServerRoot指令
 1.2.3 DocumentRoot指令
 1.2.4 DirectoryIndex指令
 1.2.5 ServerName和ServerAlias
 1.2.6 Include指令
 1.2.7 Define和UnDefine指令
 1.2.8 VirtualHost指令
 1.2.9 Options和AllowOverride指令
 1.2.10 Require指令
 1.2.11 長連接相關指令
1.3 容器類指令
 1.3.1 容器< Directory >和< Files >
 1.3.2 容器< Location >
 1.3.3 < IfDefine >、< IfModule >和< IfVersion >條件判斷
 1.3.4 < If >、< ElseIf >和< Else >容器
1.4 配置文件的合併規則

本文主要介紹介紹的是httpd的配置文件,包括一些最基本的指令、配置規則、配置合併規則。以下指令完全來自官方手冊以及我自己的總結和整理。


 

1.1 httpd命令和apachectl命令

[root@xuexi ~]# 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            : 定義一個在< IfDefine name >中使用的name,以此容器中的指令
  -d directory       : 指定ServerRoot
  -f file            : 指定配置文件
  -C "directive"     : 指定在載入配置文件前要處理的指令(directive)
  -c "directive"     : 指定在載入配置文件後要處理的指令
  -e level           : 顯示httpd啟動時的日誌調試級別
  -E file            : 將啟動信息記錄到指定文件中
  -v                 : 顯示版本號
  -V                 : 顯示編譯配置選項
  -h                 : 顯示幫助信息
  -l                 : 顯示已編譯但非動態編譯的模塊,即靜態編譯的模塊
  -L                 : 顯示靜態模塊可用的指令列表
  -t -D DUMP_VHOSTS  : 顯示虛擬主機的設置信息
  -t -D DUMP_RUN_CFG : 顯示運行參數
  -S                 : 等價於-t -D DUMP_VHOSTS -D DUMP_RUN_CFG。在調試如何解析配置文件時非常非常有用
  -t -D DUMP_MODULES : 顯示所有已被載入的模塊,包括靜態和動態編譯的模塊
  -M                 : 等價於-t -D DUMP_MODULES
  -t                 : 檢查配置文件語法
  -T                 : 不檢查DocumentRoot,直接啟動
  -X                 : 調試模式,此模式下httpd進程依賴於終端
  -k                 : 管理httpd進程,接受start|restart|graceful|graceful-stop|stop

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環境下,還可以使用apacectl statussystemctl status httpd查看httpd進程的詳細信息。

1.2 配置文件規則和常見指令

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啟動時會先進行配置文件的合併。理解合併規則非常重要,具體見配置文件合併規則

1.2.1 Listen指令

設置監聽套接字。設置方式很簡單,包括以下幾種情況:

# 監聽兩個埠
Listen 80
Listen 8000

# 監聽套接字綁定在給定地址和埠上
Listen 192.170.2.1:80
Listen 192.170.2.5:8000

1.2.2 ServerRoot指令

該指令設置httpd的安裝位置,也就是常稱之為的basedir,在此目錄下應該具有module、logs等目錄。rpm安裝的httpd的ServerRoot預設為/etc/httpd,編譯安裝的ServerRoot路徑由"--prefix"選項指定,例如/usr/local/apache。

[root@xuexi ~]# ls -l /usr/local/apache/
total 52
drwxr-xr-x  2 root root  4096 Sep 27 20:46 bin
drwxr-xr-x  2 root root  4096 Sep 27 20:46 build
drwxr-xr-x  2 root root  4096 Sep 27 20:46 cgi-bin
drwxr-xr-x  3 root root  4096 Sep 27 20:46 error
drwxr-xr-x  2 root root  4096 Sep 30 11:33 htdocs
drwxr-xr-x  3 root root  4096 Sep 27 20:46 icons
drwxr-xr-x  2 root root  4096 Sep 27 20:46 include
drwxr-xr-x  2 root root  4096 Sep 30 01:40 logs
drwxr-xr-x  4 root root  4096 Sep 27 20:46 man
drwxr-xr-x 14 root root 12288 Jul  7 01:38 manual
drwxr-xr-x  2 root root  4096 Sep 27 20:46 modules

這個指令很關鍵,安裝好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。

所以,這個指令強烈不建議做任何修改,修改是很簡單,但是牽一發而動全身。

1.2.3 DocumentRoot指令

如果說,ServerRoot是httpd中本地文件相對路徑的根,那麼DocumentRoot就是網路路徑相對路徑的根。顧名思義,DocumentRoot是文檔的根目錄,這個文檔的意思是展現在網路上的文檔。使用rpm包安裝的httpd的DocumentRoot預設值為"/var/www",編譯安裝的httpd,其DocumentRoot預設為"PREFIX/htdocs",也就是"$ServerRoot/htdocs"。

設置DocumentRoot後,將需要在網路上訪問的文件都放進此目錄下即可。

例如,假設httpd所在主機IP為192.168.100.14,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/的"/"。

1.2.4 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>

1.2.5 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和ServerName沒有任何區別。當然,為了區分基於名稱的虛擬主機,還是必須要定義ServerName。

例如,下麵幾個ServerName和ServerAlias是完全等價的。

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

1.2.6 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

如果include包含的文件不存在時,將報錯。這時可以使用IncludeOptional指令進行載入,這表示存在則載入,不存在就算了。例如下麵的第一條指令中,如果vhosts下沒有子目錄,或者子目錄中沒有".conf"文件都將失敗,而第二條指令則不會。

Include conf/vhosts/*/*.conf
IncludeOptional conf/vhosts/*/*.conf

1.2.7 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

1.2.8 VirtualHost指令

無疑,這是最重要的指令之一。用於封裝一組指令只作用於指定主機名或IP地址的虛擬主機上。

語法格式為:

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

其中addr部分可以是以下幾種情況:

  • 虛擬主機的IP地址
  • 虛擬主機IP地址對應的FQDN(不推薦)
  • 字元"*",匹配任意IP地址
  • 字元串"_default_",是"*"的別名

例如:

<VirtualHost 10.1.2.3:80>
  ServerAdmin [email protected]
  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虛擬主機

1.2.9 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

1.2.10 Require指令

Require指令

1.2.11 長連接相關指令

KeepAlive指令用於開啟和關閉長連接功能。

KeepAlive on/off

在沒有開啟長連接時,客戶端每請求一個資源都需重新建立一次TCP連接,而使用了長連接後,客戶端只需在最初請求一次TCP連接,之後就可以使用同一個TCP連接發送其他的http請求。長連接的狀態是指在服務端處理完某一個請求後,它立即進入長連接狀態以保持TCP連接不斷開,等待客戶端再次發送請求。

但長連接自身的缺陷是會一直占用著連接不釋放,所以必須得給出一個長連接的超時時間。這個超時時間由KeepAliveTimeout指令控制,進入長連接後如果在此時間間隔內客戶端還沒有發送新請求,則TCP連接自動斷開。如果在長連接狀態下,客戶端再次發送了請求,則服務端處理請求,併在處理完請求後又再次進入長連接狀態並計算KeepAliveTimeout。

此外,還可以通過指令MaxKeepAliveRequests控制每個長連接下的TCP連接的能接受的最大請求數。無疑,這個值應該設置的大一些,設置為0表示無限制。這個指令是從數量的角度控制長連接的TCP應該何時斷開。例如,在長連接超時時間內接受同一個客戶端的500個請求才斷開,然後該客戶端再有新的請求只能重新建立TCP連接。

MaxKeepAliveRequests 500

1.3 容器類指令

路徑和條件判斷容器包括:

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

1.3.1 容器< 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提供的正則。

1.3.2 容器< 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 >容器。

1.3.3 < 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 >容器之前定義。例如:

Define MyName

< 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.0.
</IfVersion>

1.3.4 < 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/16,則if段生效,否則如果屬於0/8,則elseif段生效,否則else生效
<If "-R '10.1.0.0/16'">
  #...
</If>
<ElseIf "-R '10.0.0.0/8'">
  #...
</ElseIf>
<Else>
  #...
</Else>

1.4 配置文件的合併規則

配置文件的段落以一種非常特殊的順序生效。理解配置文件的合併規則非常重要,否則配置了半天可能發現根本不會生效。

以下是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>

回到Linux系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html

回到網站架構系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7576137.html

回到資料庫系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7586194.html

轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/7636836.html

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前面提到AFNetworking是一個很強大的網路三方庫,首先你需要引入AFNetworking三方庫;如封裝的有誤還請指出,謝謝! 1.Get請求 /**Get請求 url 伺服器請求地址 success 伺服器響應返回的結果 faile 失敗的信息 */ + (void)getHttpReque ...
  • 生成二維碼圖片也是項目中常用到的,二維碼的掃描Git上有很多好用的,這裡主要說下二維碼的生成 1.普通二維碼 1.1 方法 /** 生成二維碼 QRStering:字元串 imageFloat:二維碼圖片大小 */ + (UIImage *)createQRCodeWithString:(NSStr ...
  • 去除navigationBar上那條線: ///隱藏navigationBar導航欄線(直接寫在UINavigationController-viewDidLoad方法裡面即可) UIView *backgroundView = [self.navigationBar subviews].first ...
  • 最近在做app,用的volley傳參,有一個地方傳中文參數不行(貌似是get方式),我又試了下post方式,成功了,記錄下,以後有用! ...
  • 參考資料:http://docs.oracle.com/database/122/SQLRF/Functions.htm#SQLRF006 Single-row functions return a single result row for every row of a queried table ...
  • 1、預編譯的好處 大家平時都使用過JDBC中的PreparedStatement介面,它有預編譯功能。什麼是預編譯功能呢?它有什麼好處呢? 當客戶發送一條SQL語句給伺服器後,伺服器總是需要校驗SQL語句的語法格式是否正確,然後把SQL語句編譯成可執行的函數,最後才是執行SQL語句。其中校驗語法,和 ...
  • 1》hadoop簡介: Hadoop是一個開發和運行處理大規模數據的軟體平臺,是Apache的一個用java語言實現開源軟體框架,實現在大量電腦組成的集群中對海量數據進行 分散式計算.Hadoop框架中最核心設計就是:HDFS和MapReduce,HDFS提供了海量數據的存儲,MapReduce提 ...
  • 在網上查找刪除重覆數據保留id最小的數據,方法如下: 自己使用的時候顯示報錯: [Err] 1093 - You can't specify target table ‘XXX’ for update in FROM clause 暫時不知道是什麼原因導致的。 然後想辦法分佈操作,首先篩選出有重覆u ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...