限問題排查指南:告別403 Forbidden與Permission denied)
說實(shí)話只要跑過一段時(shí)間Nginx沒人能躲過這個(gè)報(bào)錯(cuò)組合瀏覽器里一個(gè)大白板寫著403 Forbidden翻到error.log看到一行open() /xxx/index.html failed (13: Permission denied)。尤其是當(dāng)你確認(rèn)文件存在、路徑?jīng)]錯(cuò)、配置也是從默認(rèn)模板改的結(jié)果頁面死活打不開的時(shí)候那種憋屈感我太懂了。Nginx權(quán)限問題在排障里出鏡率極高但它本身并不復(fù)雜。這篇文章我會(huì)把底層邏輯講明白再按場景給可復(fù)現(xiàn)的修復(fù)步驟最后附上我平時(shí)排查的固定流程和踩坑清單爭取讓你下次碰到類似問題能在五分鐘內(nèi)定位。1. 先搞清楚Nginx權(quán)限體系的底層邏輯1.1 工作進(jìn)程是誰在跑很多人把Nginx的權(quán)限問題想得太玄其實(shí)核心就一句話運(yùn)行Nginx進(jìn)程的用戶必須對網(wǎng)頁文件有合適的訪問權(quán)限。Nginx啟動(dòng)時(shí)有個(gè)master主進(jìn)程負(fù)責(zé)加載配置、管理worker進(jìn)程。主進(jìn)程通常以root啟動(dòng)因?yàn)橐O(jiān)聽80/443這種特權(quán)端口但它干完活就會(huì)把worker進(jìn)程降權(quán)。真正處理請求、讀文件、寫日志的是那些worker進(jìn)程。worker進(jìn)程跑在哪個(gè)用戶下看配置文件里的user指令。常見發(fā)行版默認(rèn)值不一樣Debian/Ubuntu系常用www-dataCentOS/RHEL系常用nginx一些編譯安裝的版本可能直接用nobody。所以排查權(quán)限問題的第一步永遠(yuǎn)是確認(rèn)worker進(jìn)程的實(shí)際身份。光看配置文件的user指令是不夠的因?yàn)槟承┌l(fā)行版會(huì)在編譯時(shí)覆蓋默認(rèn)值或者配置里有include片段二次賦值。最可靠的辦法是直接看進(jìn)程ps -eo pid,user,comm | grep nginx輸出里以nginx: worker結(jié)尾的進(jìn)程屬于哪個(gè)用戶處理請求時(shí)就用哪個(gè)身份這是鐵律。順便提一句雖然user指令可以寫成user root;來“一勞永逸”但這是嚴(yán)重的生產(chǎn)事故隱患后文會(huì)專門解釋為什么不能這么干。1.2 目錄和文件權(quán)限到底卡在哪一層Linux的權(quán)限模型很簡單文件或目錄有owner、group、others三組身份每組有r讀、w寫、x執(zhí)行三種權(quán)限。但對Nginx這類web服務(wù)來說判斷標(biāo)準(zhǔn)要從“當(dāng)前登錄用戶”換成“worker進(jìn)程的用戶身份”。這里有個(gè)新手最容易栽跟頭的地方目錄的權(quán)限含義和文件不一樣。文件讀需要r寫需要w執(zhí)行/運(yùn)行需要x。目錄r只代表“能列出目錄里有哪些名字”w代表“能在目錄里創(chuàng)建/刪除文件”x才代表“能穿過這個(gè)目錄”。對Nginx而言訪問/data/www/site/index.html需要/data、/data/www、/data/www/site每一級目錄都包含“其他用戶可執(zhí)行”others的x的權(quán)限。哪怕只有一級目錄缺了xNginx就會(huì)上報(bào)permission denied。但注意目錄缺r并不會(huì)直接阻止訪問已知文件名的文件這就是為什么有些“目錄沒讀權(quán)限”的站點(diǎn)直接輸入完整路徑能打開但瀏覽目錄列表會(huì)403??紤]到權(quán)限配置標(biāo)準(zhǔn)安全的做法是目錄給755rwxr-xr-x文件給644rw-r--r--owner設(shè)為部署用戶或站點(diǎn)管理員。這樣owner全權(quán)控制其他所有人包括Nginx worker能讀能執(zhí)行但不能寫。1.3 SELinux這個(gè)隱藏?cái)r路虎在CentOS/RHEL及衍生發(fā)行版上大量Nginx權(quán)限問題還有一個(gè)隱形元兇SELinux。它的存在會(huì)讓“普通的Linux權(quán)限”看起來完全正常但訪問依然被拒。SELinux給每個(gè)進(jìn)程和文件都打了安全標(biāo)簽。默認(rèn)策略里Nginx進(jìn)程的域是httpd_t而網(wǎng)頁文件通常需要標(biāo)記為httpd_sys_content_t。如果你的站點(diǎn)文件放在自定義路徑比如/data/www而不是發(fā)行版默認(rèn)的/usr/share/nginx/htmlSELinux默認(rèn)不帶httpd_sys_content_t標(biāo)簽Nginx就會(huì)在系統(tǒng)調(diào)用層被攔截。最典型的現(xiàn)象是ll看文件權(quán)限一切正常nginx用戶也有權(quán)限但日志照樣報(bào)Permission denied。這時(shí)候必須檢查SELinuxgetenforce輸出Enforcing就說明SELinux在生效。再用ls -Z看文件標(biāo)簽ls -Zd /data/www如果標(biāo)簽是default_t而不是httpd_sys_content_t就可以實(shí)錘了。修SELinux的正確姿勢不是直接setenforce 0關(guān)掉雖然很多人這么干而是按后文方案給文件打標(biāo)簽。后面我在解決方案里會(huì)展開講。2. 認(rèn)識兩類最典型的權(quán)限報(bào)錯(cuò)2.1 403 Forbidden的兩種截然不同的成因我見過太多人一看403就急著調(diào)目錄權(quán)限結(jié)果越調(diào)越亂。其實(shí)403 Forbidden在Nginx里有兩種完全不同的來源必須靠error.log區(qū)分。第一種是系統(tǒng)調(diào)用層錯(cuò)誤。Nginx嘗試用worker進(jìn)程身份去open()文件內(nèi)核返回EACCESerrno 13。這種錯(cuò)誤在error.log里的特征是包含Permission denied字樣并且會(huì)帶上失敗的操作路徑。比如[error] 12345#0: *678 open() /usr/share/nginx/html/index.html failed (13: Permission denied)這種才是真正的“權(quán)限”問題需要按第3章的方案去修目錄、owner、SELinux標(biāo)簽。第二種是Nginx配置層的拒絕。文件本身讀得到但Nginx的配置邏輯決定不給你看。典型場景[error] 12345#0: *789 directory index of /data/www/site/ is forbidden這種情況通常是目錄里沒有index.html/index.php等索引文件而配置里又沒開autoindex on;。簡單說Nginx進(jìn)得了目錄、讀得到文件列表但不知道默認(rèn)該顯示哪個(gè)文件。這不太算權(quán)限問題更像配置問題。還有一種配置層拒絕是location塊里顯式寫了deny all;或做了IP封禁。區(qū)分這兩種403的方法很簡單去error.log看關(guān)鍵字。有“permission denied”的走系統(tǒng)權(quán)限排查只有“directory index is forbidden”的檢查索引文件和index指令。2.2 error.log里第13號錯(cuò)誤代表什么系統(tǒng)調(diào)用錯(cuò)誤后面跟的數(shù)字是從errno全局變量來的。13: Permission denied對應(yīng)EACCES意思是“權(quán)限不足操作不被允許”。并不是只有文件權(quán)限會(huì)導(dǎo)致EACCES像Unix socket連接、寫日志、創(chuàng)建臨時(shí)文件都可能觸發(fā)。常見的幾個(gè)errno在Nginx日志里出現(xiàn)的頻率也高我整理了一下errno含義Nginx日志里的典型表現(xiàn)13EACCES權(quán)限不足open() failed (13: Permission denied)2ENOENT文件/目錄不存在open() failed (2: No such file or directory)21EISDIR路徑是目錄open() /path failed (21: Is a directory)30EROFS文件系統(tǒng)只讀open() failed (30: Read-only file system)111ECONNREFUSED連接被拒connect() failed (111: Connection refused)排查時(shí)不要只盯著13不放有時(shí)候2號和13號是連鎖反應(yīng)比如Nginx想訪問某目錄下的默認(rèn)索引文件但目錄本身對worker進(jìn)程沒有x權(quán)限內(nèi)核可能返回的不是13而是2當(dāng)作不存在。所以“文件明明存在但報(bào)No such file or directory”時(shí)也要回頭看權(quán)限。3. 分場景破解權(quán)限問題3.1 靜態(tài)文件與站點(diǎn)目錄的權(quán)限修復(fù)最典型也最好修的場景靜態(tài)站或前端項(xiàng)目部署到服務(wù)器上結(jié)果訪問直接403。我習(xí)慣按這個(gè)順序處理第一步確認(rèn)worker進(jìn)程用戶。ps -eo user,comm | grep nginx假設(shè)返回nginx那所有判斷都以nginx用戶能否讀文件為基準(zhǔn)。第二步檢查目錄鏈路權(quán)限。namei -l /data/www/site/index.html這條命令會(huì)列出從根目錄到目標(biāo)文件的每一層權(quán)限一眼就能看出哪級目錄缺x或r。比如說f: /data/www/site/index.html drwxr-xr-x root root / drwxr-xr-x root root data drwxr-xr-x root root www drwx------ root root site -rw-r--r-- root root index.html問題立刻就清楚了site目錄權(quán)限是700只有root能進(jìn)nginx用戶被拒之門外。修復(fù)方式是把目錄改成755chmod 755 /data/www/site如果不想用迭代的chmod命令可以一條命令遞推設(shè)置目錄和文件權(quán)限find /data/www/site -type d -exec chmod 755 {} \; find /data/www/site -type f -exec chmod 644 {} \;第三步把owner調(diào)整為更適合協(xié)作的模式。如果部署用戶是deploy但它要把文件放在/data/www下給nginx讀有幾種選擇直接把文件owner改成nginxchown -R nginx:nginx /data/www/site更推薦的做法owner保持deploygroup設(shè)成nginx目錄權(quán)限755文件權(quán)限640以上再把nginx用戶加入deploy組或文件所在組。這樣開發(fā)部署方便Nginx也能讀權(quán)責(zé)邊界清晰。實(shí)操里我一般不用nginx作owner因?yàn)楹罄m(xù)程序要更新文件時(shí)會(huì)很別扭。把項(xiàng)目交給專用的部署賬戶然后把站點(diǎn)目錄的group設(shè)成nginx更順手。第四步檢查SELinux標(biāo)簽。如果你在CentOS系上文件權(quán)限改完還是403立刻檢查標(biāo)簽chcon -R -t httpd_sys_content_t /data/www/site但chcon是臨時(shí)生效重啟或執(zhí)行restorecon后會(huì)恢復(fù)。正規(guī)做法是用semanage fcontext寫持久化規(guī)則semanage fcontext -a -t httpd_sys_content_t /data/www/site(/.*)? restorecon -Rv /data/www/site如果后續(xù)還會(huì)部署新文件到該目錄這個(gè)持久化規(guī)則會(huì)自動(dòng)給新文件打正確的標(biāo)簽一勞永逸。3.2 PHP-FPM的Unix Socket權(quán)限沖突PHP類站點(diǎn)比如各種PHP框架、WordPress跑Nginx時(shí)靜態(tài)文件可能一切正常但一旦訪問PHP文件報(bào)錯(cuò)就變成了[error] connect() to unix:/run/php-fpm/php-fpm.sock failed (13: Permission denied)這種和網(wǎng)頁文件的Permission denied完全不是一回事。Nginx在這里是要把自己當(dāng)成客戶端去連接一個(gè)Unix domain socket而連接socket的權(quán)限由socket文件的權(quán)限和SELinux布爾值決定。先看socket文件本身ls -l /run/php-fpm/php-fpm.sock常見輸出是srw-rw---- 1 root php-fpm 0 某日某時(shí) php-fpm.socksocket的owner是rootowner是php-fpm組。而Nginx worker進(jìn)程是nginx用戶它不屬于php-fpm組。srw-rw----表示除了root和php-fpm組成員其他人都無法讀也無法寫nginx自然連不上。解決辦法有四種按推薦度排序方案A改PHP-FPM的socket owner/group為nginx。在PHP-FPM的pool.d/www.conf里找listen.owner nginx listen.group nginx listen.mode 0660改完重啟PHP-FPMsocket的ower/group就變成nginx了Nginx就能連。這種最省心。方案B把nginx用戶加進(jìn)php-fpm組。usermod -a -G php-fpm nginx需要讓Nginx重新加載用戶組信息通常得重啟服務(wù)。效果也是讓nginx用戶獲得socket訪問權(quán)。方案C把socket權(quán)限放寬到0666。修改listen.mode 0666。能用但不建議因?yàn)檫@是把所有本地用戶都敞開寫入socket的權(quán)限等于把后門打開給同機(jī)器的其他進(jìn)程。CenterOS系上還有第五個(gè)隱藏坑即使socket權(quán)限看起來全對可能還是連不上因?yàn)镾ELinux會(huì)攔。這時(shí)要檢查并打開布爾開關(guān)setsebool -P httpd_can_network_connect 1httpd_can_network_connect控制Nginx是否能發(fā)起網(wǎng)絡(luò)連接包括訪問socket。在CentOS 7/8上這個(gè)值默認(rèn)往往是off。順帶一提如果你用Nginx反代到本機(jī)某端口遇到connection refused或13錯(cuò)誤很多時(shí)候也是這個(gè)布爾值的鍋。我自己踩過最深的坑是改了socket權(quán)限之后忘了檢查SELinux結(jié)果還報(bào)13錯(cuò)。后來把兩個(gè)維度并成一套檢查流程ls -l看Unix權(quán)限getsebool httpd_can_network_connect看SELinux布爾量一氣呵成。3.3 反向代理與緩存目錄的權(quán)限邊界Nginx做反向代理時(shí)目錄權(quán)限問題主要在緩存目錄和臨時(shí)目錄。如果配置了proxy_cache而緩存目錄沒有正確權(quán)限會(huì)出現(xiàn)[error] mkdir() /var/cache/nginx/proxy_temp failed (13: Permission denied)這里要理解Nginx對臨時(shí)目錄和緩存目錄的權(quán)限要求worker進(jìn)程必須對它們有完全的讀寫執(zhí)行權(quán)限。因?yàn)镹ginx在代理大文件、響應(yīng)體時(shí)會(huì)先把內(nèi)容寫入臨時(shí)文件快滿或超閾值時(shí)再移動(dòng)到目標(biāo)位置。默認(rèn)臨時(shí)目錄配置在http塊里proxy_temp_path /var/cache/nginx/proxy_temp; proxy_cache_path /var/cache/nginx/proxy_cache levels1:2 keys_zonemy_cache:10m max_size10g inactive60m use_temp_pathon;把這兩類目錄的owner統(tǒng)一給nginx是正確的做法mkdir -p /var/cache/nginx/proxy_temp /var/cache/nginx/proxy_cache chown -R nginx:nginx /var/cache/nginx chmod -R 700 /var/cache/nginx權(quán)限給700就夠反正是Nginx自己的私有目錄越少對外開放越好。如果你用Nginx反代到上游比如負(fù)載均衡到多個(gè)后端節(jié)點(diǎn)還要留意上游返回內(nèi)容很大時(shí)Nginx寫臨時(shí)文件會(huì)迅速占滿磁盤。這雖然不算權(quán)限問題但經(jīng)常和權(quán)限問題一起出現(xiàn)排查時(shí)我建議順手看下df -h和目錄所屬空間是否夠用。3.4 日志文件寫不進(jìn)去怎么辦Nginx自身有兩個(gè)日志相關(guān)的大坑一是access.log/error.log本身寫不了導(dǎo)致啟動(dòng)失敗二是站點(diǎn)的業(yè)務(wù)日志目錄權(quán)限不對導(dǎo)致應(yīng)用報(bào)錯(cuò)。Nginx日志寫不了的場景error.log里大概率會(huì)直接出現(xiàn)[emerg] open() /var/log/nginx/error.log failed (13: Permission denied)這種往往是/var/log/nginx目錄的owner或者父目錄權(quán)限被動(dòng)過worker進(jìn)程和master進(jìn)程在啟動(dòng)階段沒權(quán)限創(chuàng)建或追加日志文件。解決辦法mkdir -p /var/log/nginx chown -R nginx:nginx /var/log/nginx用nginx -t驗(yàn)證配置沒問題后再啟動(dòng)服務(wù)。要是還不行注意看一下/var/log自身是不是權(quán)限異常某些加固腳本會(huì)把所有日志目錄都改成700 root:root那Nginx是真的寫不進(jìn)去。業(yè)務(wù)日志目錄的坑沒法用Nginx配置解決。比如PHP應(yīng)用要寫/data/www/site/runtime日志目錄而Nginx worker用戶的上下文是nginx應(yīng)用進(jìn)程PHP-FPM也是nginx用戶如果該目錄owner是別的用戶且不可寫應(yīng)用就會(huì)報(bào)錯(cuò)。這類問題排查時(shí)要區(qū)分“給Nginx的權(quán)限”和“給應(yīng)用運(yùn)行用戶的權(quán)限”別全部套用Nginx邏輯。我經(jīng)歷過一次所有改動(dòng)都正確但仍寫不進(jìn)去的情況最后發(fā)現(xiàn)是/data/www/site/runtime被chattr i加了不可變標(biāo)志。這個(gè)冷門問題值得留意排查時(shí)可執(zhí)行l(wèi)sattr /data/www/site/runtime如果看到----i--------移除標(biāo)志后用chattr -i就行。4. 一套可落地的排查流程4.1 從進(jìn)程用戶到目錄鏈路的五步檢查爛熟于心的排查順序能幫你節(jié)省大量時(shí)間。我自己總結(jié)的五步法基本覆蓋了90%的Nginx權(quán)限問題第一步最小化確認(rèn)worker身份。執(zhí)行ps -eo user,comm | grep nginx第二步確認(rèn)報(bào)錯(cuò)路徑與文件。從error.log里拿到具體路徑不要憑感覺猜目錄。日志里的路徑可能有前綴比如/usr/share/nginx/html和實(shí)際站點(diǎn)目錄不是一回事務(wù)必以日志為準(zhǔn)。第三步逐級查看目錄鏈路權(quán)限。用namei -l或手動(dòng)ls -ld每個(gè)目錄確認(rèn)每一級都有“其他人可執(zhí)行”權(quán)限。第四步確認(rèn)文件權(quán)限。文件至少要644至少不能對worker用戶封鎖讀權(quán)限。第五步查SELinux狀態(tài)和標(biāo)簽。特別在CentOS/RHEL系上這一步不能省。這五步執(zhí)行下來基本能定位“是普通Linux權(quán)限還是SELinux標(biāo)簽”的問題。如果五步全對還是報(bào)Permission denied我才會(huì)考慮是不是有chattr加固、只讀掛載或其他文件系統(tǒng)層因素。4.2 模擬用戶訪問定位權(quán)限盲區(qū)有一個(gè)特別高效的驗(yàn)證思路切換到worker用戶身份真實(shí)模擬一次Nginx訪問。先確認(rèn)worker用戶比如是nginx然后執(zhí)行sudo -u nginx cat /data/www/site/index.html如果cat讀得出來說明普通Linux權(quán)限沒問題。如果提示permission denied那就可以直接定位到具體是哪個(gè)目錄的哪個(gè)環(huán)節(jié)缺權(quán)限sudo -u nginx ls /data/www/site/對比兩條命令的結(jié)果就能判斷到底卡在目錄穿越x權(quán)限還是文件讀取r權(quán)限上。PHP-FPM socket場景也能模擬sudo -u nginx curl --unix-socket /run/php-fpm/php-fpm.sock http://localhost/如果curl訪問socket返回權(quán)限錯(cuò)誤說明socket的owner/group或SELinux布爾量有問題如果curl返回HTTP響應(yīng)那Nginx配置或PHP進(jìn)程本身可能是主要嫌疑。這個(gè)模擬法的好處是能區(qū)分“文件系統(tǒng)的狀態(tài)”和“Nginx的配置行為”。很多時(shí)候文件權(quán)限沒問題、SELinux也正常但Nginx依然403原因就跑到Nginx配置層去了。通過模擬命令可以直接把配置層問題從權(quán)限問題中摘出來。5. 常見問題速查與避坑筆記5.1 高頻問題對照表我把這幾年在群里、社區(qū)里見過的高頻Nginx權(quán)限問題濃縮成一張速查表實(shí)戰(zhàn)時(shí)可對照著用報(bào)錯(cuò)特征可能原因首選修復(fù)open() failed (13: Permission denied)文件在站點(diǎn)目錄目錄鏈路缺x或文件缺rSELinux標(biāo)簽不對namei -l定位缺權(quán)限層chmod 755/644SELinux下用restorecon -Rvdirectory index of /xxx is forbidden目錄下無index文件且未開autoindex放index文件或加autoindex on;慎用connect() to unix:/xxx.sock failed (13: Permission denied)socket權(quán)限不對調(diào)listen.owner/group或在PHP-FPM配置中指定nginx用戶mkdir() xxx failed (13: Permission denied)緩存目錄/臨時(shí)目錄owner不對chown -R nginx:nginx緩存目錄access.log/error.log open() failed (13)日志目錄owner不對或日志目錄被鎖chown -R nignx:nginx /var/log/nginx查lsattr反代到本機(jī)端口報(bào)13或111SELinux布爾量關(guān)閉setsebool -P httpd_can_network_connect 1文件存在但報(bào)2號No such file某級目錄權(quán)限缺x內(nèi)核“看不見”補(bǔ)目錄的x權(quán)限光看表不一定覆蓋所有場景但排障的時(shí)候先對照一遍大概率能省去你從零摸索的時(shí)間。5.2 幾個(gè)容易忽略的細(xì)節(jié)這一節(jié)分享幾個(gè)我在實(shí)際操作中容易踩到的細(xì)節(jié)常規(guī)文檔基本不提但影響實(shí)打?qū)?。?xì)節(jié)一Nginx對目錄的權(quán)限要求比想象中嚴(yán)格。目錄權(quán)限至少要711才能讓Nginx正常穿越750也能穿越owner可讀寫執(zhí)行、group可讀執(zhí)行、others沒有權(quán)限。這意味著如果你把站點(diǎn)目錄放在某用戶home目錄下比如/home/deploy/www而home目錄權(quán)限是700Nginx就永遠(yuǎn)進(jìn)不去。很多人把站點(diǎn)放在home下文件權(quán)限全對就是403原因就在home目錄沒有“其他人可執(zhí)行”。這種場景要么把目錄挪到/var/www或/data/www要么調(diào)整home目錄權(quán)限一般不建議。細(xì)節(jié)二不要輕易用user root;。我看到過幾次有人為了省事直接把Nginx worker設(shè)成root這樣的后果是任何漏洞都直接以root權(quán)限執(zhí)行。一旦PHP或其他模塊被攻擊影響是災(zāi)難性的。正規(guī)做法永遠(yuǎn)是給worker一個(gè)低權(quán)限賬號并把站點(diǎn)文件通過合理的方式group、ACL、sudo部署交給這個(gè)賬號訪問。細(xì)節(jié)三改完權(quán)限記得測試重載。修改配置文件或權(quán)限后先跑nginx -t確認(rèn)語法沒問題再用nginx -s reload平滑重載。很多時(shí)候權(quán)限問題不是沒修好而是改了配置沒生效或者語法報(bào)錯(cuò)導(dǎo)致根本沒加載。細(xì)節(jié)四ACL權(quán)限也可能參與。當(dāng)ls普通權(quán)限看著沒問題但Nginx還是13錯(cuò)時(shí)檢查ACLgetfacl /data/www/site如果ACL里有mask或者某條對特定用戶拒絕的記錄會(huì)直接影響Nginx的訪問判斷。用setfacl -R -m u:nginx:rX /data/www/site可以追加ACL授權(quán)這個(gè)方案特別適合那些不方便改owner的共享目錄場景。細(xì)節(jié)五日志輪轉(zhuǎn)也會(huì)制造權(quán)限問題。logrotate輪轉(zhuǎn)日志時(shí)如果新創(chuàng)建的日志文件owner是root而Nginx接下來要寫入就會(huì)遇到13錯(cuò)。排查時(shí)如果看到日志報(bào)錯(cuò)時(shí)間點(diǎn)集中在輪轉(zhuǎn)前后大概率就是輪轉(zhuǎn)腳本創(chuàng)建的文件權(quán)限不對。解決方式是在logrotate配置里加create 640 nginx adm這類參數(shù)確保輪轉(zhuǎn)后文件owner正確。結(jié)尾說點(diǎn)個(gè)人體會(huì)處理Nginx權(quán)限問題這幾年我最深的體會(huì)是這問題根本不算難難的是養(yǎng)成系統(tǒng)性排查習(xí)慣。很多人一看到403就直接把手頭文件chmod 777改完了還不行就開始懷疑配置、懷疑防火墻、懷疑網(wǎng)絡(luò)繞一大圈回來才知道是目錄上一級少了個(gè)x權(quán)限。與其這樣不如按前面那五步來確認(rèn)worker身份、看日志拿路徑、查目錄鏈路、查文件權(quán)限、查SELinux。每一步都用一個(gè)命令驗(yàn)證基本上兩分鐘就能定位。另外一個(gè)讓我吃過虧的細(xì)節(jié)是修改完權(quán)限后務(wù)必要重新加載Nginx和PHP-FPM。Nginx的root權(quán)限配置改了要重載PHP-FPM的listen.owner改了要重啟SELinux布爾量改了最好也重啟一下相關(guān)服務(wù)。很多人改完不重啟就在那兒反復(fù)測浪費(fèi)時(shí)間不說還容易誤判。如果你按照這個(gè)流程排完之后發(fā)現(xiàn)權(quán)限完全正常但問題依舊最后再分享一個(gè)小技巧去看error.log的完整上下文別只盯著最后一行。有時(shí)候權(quán)限問題不是根因而是連鎖反應(yīng)。比如后端PHP進(jìn)程崩潰了Nginx連不上socket日志先報(bào)connect失敗后報(bào)permission denied你把全部精力花在處理socket權(quán)限上結(jié)果后端一啟動(dòng)就全好了。前后文結(jié)合著看才能避免白忙一場。