記一次nginx訪問(wèn)快捷方式指向的文件夾失敗的排查解決過(guò)程
起因是項(xiàng)目上有一個(gè)文件域名,dns解析到linux系統(tǒng)的服務(wù)器上,有一個(gè)nginx服務(wù)反向代理了一個(gè)位于nas掛載盤(pán)內(nèi)的文件目錄,現(xiàn)在有一個(gè)新需求是讓客戶還是通過(guò)這個(gè)域名作為訪問(wèn)入口,訪問(wèn)同樣位于nas盤(pán)中和這個(gè)目錄同級(jí)的另一個(gè)目錄內(nèi)的文件。
比如通過(guò)nginx反向代理訪問(wèn)的nas盤(pán)下的目錄路徑為/mnt/picture/,訪問(wèn)的url為:https://picture.test.cn/cache/20260101/1749690185966.jpg
和picture同級(jí)的目錄路徑為:/mnt/bak/,期望的訪問(wèn)url為:https://picture.test.cn/bak/20251024/1749690185966.jpg
我第一時(shí)間想到的就是通過(guò)軟連接的方式,將/mnt/bak目錄軟連接到/mnt/picture/bak目錄:
ln -s /mnt/bak/ /mnt/picture/bak
nginx的配置簡(jiǎn)略如下:
server {
listen 443;
server_name picture.test.cn;
...
location / {
root /mnt/picture/;
}
}
訪問(wèn)沒(méi)有問(wèn)題,當(dāng)然還可以通過(guò)增加一個(gè)location,使用bak關(guān)鍵字代理/mnt/bak/目錄。
本地開(kāi)發(fā)機(jī)器是windwos10,在一個(gè)盤(pán)符下創(chuàng)建了兩個(gè)文件夾模擬了linux機(jī)器上的掛載盤(pán)目錄進(jìn)行開(kāi)發(fā)測(cè)試,nginx的配置簡(jiǎn)略如下:
server {
listen 8066;
server_name picture.test.cn;
location / {
root D:/tmp/mnt/picture/;
}
}
兩個(gè)目錄分別是:D:/tmp/mnt/picture/、D:/tmp/mnt/bak
我在D:/tmp/mnt/picture/下創(chuàng)建了一個(gè)D:/tmp/mnt/bak目錄的快捷方式,快捷方式的名稱叫bak,hosts文件中配置域名到本機(jī)的映射。
訪問(wèn)http://picture.test.cn:8066/bak/20251024/1749690185966.jpg卻提示我文件不存在:
nginx的error日志如下:
2026/10/24 09:41:16 [error] 16584#7532: *4 CreateFile() "D:/tmp/mnt/picture/bak/20251024/1749690185966.jpg" failed (3: The system cannot find the path specified), client: 127.0.0.1, server: picture.test.cn, request: "GET /bak/20251024/1749690185966.jpg HTTP/1.1", host: "picture.test.cn:8066"
明明我可以在文件系統(tǒng)中點(diǎn)擊快捷方式進(jìn)入對(duì)應(yīng)的文件夾,為啥nginx卻不識(shí)別,問(wèn)了下ai(不得不說(shuō)現(xiàn)在ai確實(shí)是一個(gè)好幫手),其核心原因有這些:
1.快捷方式本質(zhì)是特殊文件
Windows快捷方式(.lnk)是系統(tǒng)級(jí)符號(hào)鏈接文件,需由操作系統(tǒng)解析路徑。但Nginx作為Web服務(wù)器,僅讀取實(shí)際文件或目錄內(nèi)容,不會(huì)解析.lnk文件的目標(biāo)路徑。
2.Nginx配置依賴物理路徑
Nginx的root或alias指令需指向真實(shí)目錄(如D:\folder),若指向含快捷方式的目錄,Nginx會(huì)將快捷方式視為普通文件而非目錄入口,導(dǎo)致訪問(wèn)失敗。
3.路徑安全限制
Nginx默認(rèn)禁止訪問(wèn)路徑含符號(hào)鏈接的文件(安全策略),且Windows路徑格式(反斜杠\、中文名等)易引發(fā)兼容性問(wèn)題。
ai提供了解決方案:
1.NTFS 聯(lián)結(jié)點(diǎn)(Junction Point)實(shí)現(xiàn)類(lèi)似 Linux 軟鏈接的效果
文件系統(tǒng)需要是NTFS,以管理員身份運(yùn)行CMD:
mklink /J "D:\tmp\mnt\picture\bak" "D:\tmp\mnt\bak"
2.修改Nginx配置啟用路徑解析
nginx的location下增加如下配置:
disable_symlinks off; # 允許解析符號(hào)鏈接
其中disable_symlinks于nginx的1.1.15版本中增加,默認(rèn)開(kāi)啟,需要在編譯nginx時(shí)增加--with-file-aio參數(shù)。
通過(guò)nginx -v和nginx -V確認(rèn)項(xiàng)目上使用的nginx版本為1.22.0,服務(wù)器上的nginx也啟用了--with-file-aio參數(shù)。
為何Nginx在Linux支持軟鏈接而Windows不支持快捷方式?ai給出了回答:
- Linux:Nginx 通過(guò)系統(tǒng)調(diào)用(如 open())訪問(wèn)文件時(shí),內(nèi)核自動(dòng)解析軟鏈接路徑,服務(wù)無(wú)需額外處理。
- Windows:Nginx 直接讀取文件系統(tǒng),但 .lnk 是需解析的二進(jìn)制文件,非標(biāo)準(zhǔn)目錄入口,因此無(wú)法識(shí)別其指向的真實(shí)路徑。
按照ai給出的解決方案,我在本地windows機(jī)器上使用mklink創(chuàng)建了目錄聯(lián)結(jié):
mklink /J "D:\tmp\mnt\picture\bak" "D:\tmp\mnt\bak"
再次訪問(wèn)http://picture.test.cn:8066/bak/20251024/1749690185966.jpg已經(jīng)可以訪問(wèn)。
我讓ai詳細(xì)說(shuō)說(shuō)mklink
mklink 是 Windows 系統(tǒng)(Vista 及以上版本)提供的命令行工具,用于創(chuàng)建文件或目錄的鏈接,其功能類(lèi)似于 Linux 中的 ln 命令,但實(shí)現(xiàn)機(jī)制和類(lèi)型劃分更為復(fù)雜。以下是其核心特性和使用場(chǎng)景的詳細(xì)解析:
1.mklink 的鏈接類(lèi)型
| 類(lèi)型 | 參數(shù) | 特點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|
| 符號(hào)鏈接 | /D | 跨分區(qū)支持,需管理員權(quán)限,路徑可相對(duì)或絕對(duì),遠(yuǎn)程訪問(wèn)時(shí)可能不解析 | 需靈活路徑映射(如開(kāi)發(fā)環(huán)境配置) |
| 目錄聯(lián)結(jié) | /J | 僅限目錄,無(wú)需管理員權(quán)限,遠(yuǎn)程訪問(wèn)時(shí)自動(dòng)解析目標(biāo)路徑 | 遷移大目錄保留原始路徑(如程序文件) |
| 硬鏈接 | /H | 僅限文件,跨分區(qū)無(wú)效,刪除任一鏈接不影響其他副本 | 節(jié)省空間(如備份重復(fù)文件) |
2.關(guān)鍵差異與注意事項(xiàng)
-
權(quán)限要求
符號(hào)鏈接(/D)和文件硬鏈接(/H)需管理員權(quán)限運(yùn)行 CMD,目錄聯(lián)結(jié)(/J)則不需要。 -
路徑解析
符號(hào)鏈接支持相對(duì)路徑(如 ..\target),聯(lián)結(jié)僅支持絕對(duì)路徑。
移動(dòng)符號(hào)鏈接可能導(dǎo)致相對(duì)路徑失效,而聯(lián)結(jié)的絕對(duì)路徑仍有效。 -
跨分區(qū)限制
硬鏈接不可跨分區(qū),符號(hào)鏈接和聯(lián)結(jié)可跨分區(qū)但需目標(biāo)存在。
可以看到通過(guò)快捷方式和mklink命令創(chuàng)建出來(lái)的文件是可以同名的,但是其類(lèi)型不一樣,一個(gè)是快捷方式,一個(gè)是文件夾:

ai還提到了nginx的disable_symlinks標(biāo)簽需要防止攻擊者通過(guò)上傳符號(hào)鏈接文件訪問(wèn)/etc/passwd 等系統(tǒng)文件,我在windows上測(cè)試添加這個(gè)標(biāo)簽發(fā)現(xiàn),windows上的nginx并不支持這個(gè)標(biāo)簽,其核心限制原因如下:
1.平臺(tái)兼容性問(wèn)題
disable_symlinks 是 Nginx 針對(duì)類(lèi) Unix 系統(tǒng)(如 Linux)設(shè)計(jì)的特性,依賴文件系統(tǒng)符號(hào)鏈接權(quán)限檢查機(jī)制,而Windows NTFS 文件系統(tǒng)的符號(hào)鏈接管理邏輯與此不兼容,導(dǎo)致該指令在 Windows 環(huán)境下無(wú)效或無(wú)法正確解析。
嘗試在 Windows 配置中使用時(shí),nginx -t 會(huì)提示語(yǔ)法錯(cuò)誤或未知指令(如 unknown directive "disable_symlinks")。
2.版本無(wú)實(shí)質(zhì)支持
即使用戶使用的是較新的 Nginx 1.22.0 或更高版本,其Windows 編譯版仍未適配此功能。官方并未在 Windows 構(gòu)建中啟用相關(guān)依賴模塊(如 --with-file-aio)。
本地windwos機(jī)器只是用來(lái)開(kāi)發(fā)測(cè)試,倒是不影響,生產(chǎn)服務(wù)器上需要嚴(yán)格做好目錄權(quán)限的劃分以及在上傳文件的入口強(qiáng)校驗(yàn)文件的類(lèi)型。
本文來(lái)自博客園,作者:杜勁松,轉(zhuǎn)載請(qǐng)注明原文鏈接:http://www.rzrgm.cn/imadc/p/18938385

浙公網(wǎng)安備 33010602011771號(hào)