昨天被實習生問到這個問題時,我手裡的咖啡差點灑在鍵盤上——不是因為問題太難,而是因為這個坑我踩過太多次,甚至成了團隊內部的經典笑話。伺服器上明明在 /opt/app/current 目錄下操作,pwd 卻冷冰冰地回我一句 /opt/app/releases/v3.2.1 ,當下真的會懷疑人生。
這不是靈異事件,而是 Linux/Unix 系統裡「物理路徑」與「邏輯路徑」的捉迷藏遊戲。pwd 這個老命令有兩種模式:-P (Physical,物理路徑)和 -L (Logical,邏輯路徑)。預設行為像個牆頭草,不同系統、不同版本甚至不同 Shell 配置都可能讓它搖擺不定。當你身處一個「符號連結」(Symbolic Link)構成的目錄時,pwd 到底回傳連結本身的位置(邏輯路徑),還是最終指向的真實目錄位置(物理路徑),就成了「變高」現象的根源。
想像一下:你建了個快捷方式 /home/user/projects/current 指向實際版本 /home/user/projects/release-2024 。當你 cd /home/user/projects/current 進去後,pwd 該顯示哪條路?系統的糾結就在這裡。早期 Bourne Shell 可能老實告訴你真實路徑(物理),而 Bash 在某些設定下可能貼心地維持你輸入的「假路徑」(邏輯)。這差異在複雜的部署環境——比如用 Capistrano 或 Kubernetes 動態掛載版本目錄時——會讓腳本突然找不到檔案,因為它以為自己在 A 處,實際卻在 B 處。
解方不在技術,在習慣:
1. 手動錨定行為:關鍵時刻別賭預設值。需要絕對真實路徑時(例如寫入日誌、備份),用 pwd -P ;想維持目錄結構的「視覺路徑」(例如生成用戶可見的報告),用 pwd -L 。把這當成開車繫安全帶,養成肌肉記憶。
2. 改寫你的 Shell 預設:打開 ~/.bashrc 或 ~/.zshrc ,加一行 alias pwd=\'pwd -P\' 。從此天下太平,pwd 永遠吐真話。但小心!有些古老腳本依賴邏輯路徑,改前先在測試環境跑一遍。
3. 腳本裡的防禦性寫法:別相信環境變數 $PWD ,它常是邏輯路徑。在關鍵 Shell 腳本開頭,用 REAL_DIR=$(pwd -P) 鎖死真實位置,後續操作全部基於這個變數。這招在自動化部署裡救過我無數次。
4. 理解你的工具鏈:像 Python 的 os.getcwd() 通常回邏輯路徑,而 os.path.realpath() 才是物理路徑。Node.js 的 process.cwd() 也有類似陷阱。寫跨平台腳本時,顯式處理路徑解析是專業素養。
十年前我在東京維護一個分散式系統,就因為某台伺服器的 pwd 預設行為不同,導致批次更新腳本把新版本塞進了舊目錄,整整浪費六小時回滾。從那時起,我所有腳本開頭都強制宣告 NOWHERE=$(pwd -P) 。路徑是基礎中的基礎,基礎不牢,地動山搖。與其抱怨 pwd 變高,不如馴服它成為你的優勢。
|