態(tài)庫搜索路徑與可執(zhí)行文件PATH配置指南)
Ubuntu 18.04 上添加動(dòng)態(tài)庫搜索路徑和可執(zhí)行文件 PATH是個(gè)老生常談但幾乎每個(gè)月都能在群里看到有人卡住的話題。十次里有八次編譯亂成一團(tuán)最后程序起不來說一句error while loading shared libraries你對(duì)著屏幕發(fā)呆不知道系統(tǒng)到底在哪個(gè)環(huán)節(jié)把庫丟了。這篇文章我打算把“加路徑”這件事一次性拆透動(dòng)態(tài)庫該怎么加、可執(zhí)行文件路徑該怎么加、臨時(shí)和永久分別用哪個(gè)配置每一步背后的加載機(jī)制是什么以及我這些年踩過的那些坑和排查習(xí)慣。適合所有在 Ubuntu 18.04 上做開發(fā)、部署第三方庫或自制工具的人不管你是剛開始配環(huán)境的 C 新手還是在服務(wù)器上折騰推理服務(wù)的老工程師都能從這里拿到直接能用的方案。先說一個(gè)最常見的場(chǎng)景。你從源碼編譯了一個(gè)程序編譯時(shí)用了-L/path/to/libs指定鏈接路徑鏈接成功可一運(yùn)行就報(bào)找不到共享庫。原因很簡(jiǎn)單編譯時(shí)的-L只告訴鏈接器“鏈接時(shí)去哪找”運(yùn)行時(shí)動(dòng)態(tài)鏈接器ld.so根本不看-L它有自己的搜索規(guī)則。這就是很多人第一次接觸動(dòng)態(tài)庫路徑配置時(shí)的困惑來源。理解這一點(diǎn)后面的所有配置方法就都有了邏輯基礎(chǔ)。1. 為什么需要手動(dòng)加路徑先搞清系統(tǒng)是怎么“找”東西的1.1 動(dòng)態(tài)庫的搜索順序與默認(rèn)目錄Linux 下程序啟動(dòng)后由動(dòng)態(tài)鏈接器負(fù)責(zé)加載它依賴的.so文件。這個(gè)鏈接器在 Ubuntu 18.04 上是ld-2.27.so通常通過/lib64/ld-linux-x86-64.so.2路徑調(diào)用。它的查找順序大致是編譯時(shí)寫進(jìn)二進(jìn)制文件的RPATH/RUNPATH路徑然后是環(huán)境變量LD_LIBRARY_PATH指定的目錄接著是ldconfig生成的緩存文件/etc/ld.so.cache最后才是系統(tǒng)默認(rèn)目錄/lib、/usr/lib以及多架構(gòu)目錄/lib/x86_64-linux-gnu、/usr/lib/x86_64-linux-gnu。之所以“找不到”絕大多數(shù)情況下是因?yàn)槟愕?so放在 /opt、/usr/local/lib 這類非默認(rèn)目錄下又沒被ldconfig收錄??梢杂胠dconfig -p查看當(dāng)前緩存里有哪些庫。比如我想確認(rèn)系統(tǒng)認(rèn)不認(rèn)識(shí) libonnxruntime.so就執(zhí)行l(wèi)dconfig -p | grep onnxruntime如果輸出為空說明鏈接器根本沒把它納入搜索范圍運(yùn)行時(shí)報(bào)錯(cuò)是必然的。打個(gè)比方動(dòng)態(tài)鏈接器就像你手機(jī)上的應(yīng)用商店它只從自己已收錄的列表里找 App。你手動(dòng)下載的 APK 不管放在哪個(gè)文件夾不“安裝入庫”之前商店都不會(huì)在搜索結(jié)果里展示它。Linux 的“入庫”動(dòng)作就是ldconfig。1.2 可執(zhí)行文件的 PATH 查找機(jī)制可執(zhí)行文件的查找邏輯比動(dòng)態(tài)庫簡(jiǎn)單得多但也有人在這上面浪費(fèi)過時(shí)間。你在終端敲一個(gè)命令Shell 默認(rèn)按PATH環(huán)境變量里列出的目錄順序逐個(gè)查找同名文件找到第一個(gè)就執(zhí)行。如果全部找完都沒有就報(bào)command not found。Ubuntu 18.04 的默認(rèn) PATH 通常包含/usr/local/sbin、/usr/local/bin、/usr/sbin、/usr/bin、/sbin、/bin以及你用戶目錄下的~/.local/bin如果存在。第三方軟件如果裝在/opt/xxx/bin、~/tools這類目錄下系統(tǒng)自然找不到。這時(shí)候要么把對(duì)應(yīng)目錄加進(jìn) PATH要么在已在 PATH 里的目錄下做軟鏈接兩種思路我會(huì)在第三章詳細(xì)說。動(dòng)態(tài)庫和可執(zhí)行文件的查找機(jī)制有本質(zhì)區(qū)別前者依賴ld.so的動(dòng)態(tài)加載規(guī)則后者依賴 Shell 的環(huán)境變量 PATH。所以你以為“把目錄加進(jìn) PATH 就萬事大吉”對(duì)可執(zhí)行文件沒錯(cuò)但對(duì)動(dòng)態(tài)庫完全無效——很多人在這一步誤入歧途。2. 動(dòng)態(tài)庫路徑配置臨時(shí)、用戶級(jí)、系統(tǒng)級(jí)三個(gè)層次2.1 臨時(shí)生效LD_LIBRARY_PATH 的適用場(chǎng)景與陷阱最簡(jiǎn)單粗暴的方式是設(shè)置LD_LIBRARY_PATH。它告訴動(dòng)態(tài)鏈接器在搜索緩存之前先去這些目錄里找?guī)臁S梅ㄈ缦耬xport LD_LIBRARY_PATH/opt/onnxruntime/lib:$LD_LIBRARY_PATH ./your_program注意我特意保留了后面的:$LD_LIBRARY_PATH這是防止把已有的路徑覆蓋掉。如果你寫成export LD_LIBRARY_PATH/opt/onnxruntime/lib就徹底丟棄了原來環(huán)境變量里可能存在的其他路徑這在復(fù)雜的開發(fā)環(huán)境里是個(gè)隱患。這種方式的生效范圍只有當(dāng)前終端會(huì)話關(guān)掉終端就失效。所以它適合臨時(shí)驗(yàn)證不確定路徑對(duì)不對(duì)、只跑一次、不想污染環(huán)境的時(shí)候最合適。但我不建議日常開發(fā)長(zhǎng)期依賴它因?yàn)槊看未蜷_新終端都要重新 export而且它有個(gè)比較坑的特性——優(yōu)先級(jí)比ld.so.cache還高。這意味著如果 LD_LIBRARY_PATH 里存在同名但版本不同的庫系統(tǒng)會(huì)優(yōu)先加載這個(gè)版本從而掩蓋掉你辛辛苦苦配置好的 ldconfig 結(jié)果。2.2 用戶級(jí)持久化寫入 ~/.bashrc 要理解加載時(shí)機(jī)如果你希望某個(gè)用戶每次打開終端都能自動(dòng)帶上某個(gè)庫目錄最直接的做法是把 export 命令寫進(jìn)~/.bashrcecho export LD_LIBRARY_PATH/opt/onnxruntime/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc這里有一個(gè)很多人沒搞明白的細(xì)節(jié)bash 讀取配置文件是有分層的。~/.bashrc是交互式非登錄 Shell 啟動(dòng)時(shí)讀取而~/.profile或~/.bash_profile是登錄 Shell 啟動(dòng)時(shí)讀取。Ubuntu 桌面環(huán)境下打開終端默認(rèn)是交互式非登錄 Shell所以寫進(jìn).bashrc一定能被終端讀取但如果你通過 SSH 登錄、或者在圖形桌面啟動(dòng)某些應(yīng)用程序情況就不一樣了。舉一個(gè)我實(shí)際遇到的案例。有人把庫路徑寫進(jìn) .bashrc 后終端里跑程序一切正常但通過桌面圖標(biāo)啟動(dòng)的 GUI 程序還是報(bào)找不到共享庫。原因就是圖形會(huì)話的進(jìn)程不是從 bash 啟動(dòng)的根本不讀 .bashrc。如果遇到這類情況要么把配置改成系統(tǒng)級(jí)要么在.desktop啟動(dòng)文件里手動(dòng)加上LD_LIBRARY_PATH環(huán)境變量。用戶級(jí)配置還有個(gè)局限它只對(duì)配置的這個(gè)用戶有效。如果部署服務(wù)時(shí)使用 systemd 或 Docker服務(wù)的環(huán)境變量又是另一套體系bashrc 里的內(nèi)容完全不會(huì)被讀取到。所以判斷“用戶級(jí)夠不夠用”時(shí)先想清楚程序是由誰來啟動(dòng)的。2.3 系統(tǒng)級(jí)持久化/etc/ld.so.conf.d ldconfig 的標(biāo)準(zhǔn)姿勢(shì)真正意義上的“入庫”操作是修改/etc/ld.so.conf.d/下的配置文件然后執(zhí)行sudo ldconfig。這是我最推薦的生產(chǎn)環(huán)境做法也是官方文檔里明確推薦的方式。具體步驟sudo tee /etc/ld.so.conf.d/onnxruntime.conf EOF /opt/onnxruntime/lib EOF sudo ldconfig執(zhí)行完ldconfig后系統(tǒng)會(huì)掃描所有 conf 文件里的目錄、生成新的/etc/ld.so.cache文件把對(duì)應(yīng)路徑下的動(dòng)態(tài)庫登記進(jìn)緩存。之后任何用戶、任何進(jìn)程啟動(dòng)相關(guān)程序都能正確找到庫。這里要特別強(qiáng)調(diào)三個(gè)坑。第一寫進(jìn) conf 文件的必須是絕對(duì)路徑寫相對(duì)路徑不報(bào)錯(cuò)但也不生效純屬自欺欺人。第二新加的庫路徑要重新執(zhí)行l(wèi)dconfig才會(huì)被掃描如果改了配置文件忘了執(zhí)行依然找不到。第三不要輕易刪掉自帶的 conf 文件比如libc.conf里通常包含了/usr/local/lib如果你刪掉它大量安裝在/usr/local/lib下的庫都會(huì)失聯(lián)系統(tǒng)里一半第三方軟件都會(huì)出問題。我習(xí)慣在執(zhí)行l(wèi)dconfig之前先看一眼現(xiàn)有配置ls /etc/ld.so.conf.d/確認(rèn)沒有重復(fù)路徑然后執(zhí)行sudo ldconfig -v觀察掃描輸出確認(rèn)新加的目錄被正確讀取。這個(gè)-v參數(shù)雖然輸出很啰嗦但能第一時(shí)間發(fā)現(xiàn)路徑不存在之類的低級(jí)錯(cuò)誤。3. 可執(zhí)行文件路徑配置PATH 修改與軟鏈接方案3.1 PATH 的臨時(shí)設(shè)置與持久化寫法給可執(zhí)行文件添加路徑最常見的就是修改 PATH。臨時(shí)設(shè)置同樣用 exportexport PATH/opt/onnxruntime/bin:$PATH這里把新目錄放在最前面意味著系統(tǒng)會(huì)優(yōu)先找到這個(gè)目錄里的同名命令。這個(gè)順序很重要如果你把/opt/xxx/bin放在 PATH 末尾而/usr/bin里恰好有個(gè)同名工具系統(tǒng)會(huì)執(zhí)行老版本你會(huì)陷入“明明配置了怎么不生效”的困惑中。持久化寫法和 LD_LIBRARY_PATH 類似寫進(jìn)~/.bashrcecho export PATH/opt/onnxruntime/bin:$PATH ~/.bashrc source ~/.bashrc但 PATH 的修改有個(gè)特殊風(fēng)險(xiǎn)命令本身依賴 PATH。如果你在 export 的時(shí)候沒有保留原來的$PATH終端立刻會(huì)找不到 ls、cat 等基礎(chǔ)命令。我見過有人手滑寫成export PATH/opt/xxx/bin回車之后眼前一片command not found最后只能靠/bin/ls這種絕對(duì)路徑慢慢搶救。所以寫 PATH 時(shí)刻記住一個(gè)原則永遠(yuǎn)帶上:$PATH尾巴。Ubuntu 環(huán)境里還有一個(gè)配置文件叫/etc/environment有些人喜歡把 PATH 寫在這里。這個(gè)文件的格式不允許寫變量引用比如$PATH并且修改后要重新登錄才生效而且只對(duì)登錄會(huì)話有效對(duì) systemd 服務(wù)也沒有直接作用。我個(gè)人認(rèn)為在沒有特殊需求的情況下PATH 的正常修改就寫 .bashrc 或 /etc/profile.d/沒必要碰 /etc/environment可維護(hù)性反而更好。3.2 軟鏈接另一種省事的思路很多第三方工具自帶的動(dòng)態(tài)庫和可執(zhí)行文件都躺在同一個(gè)目錄下比如/opt/xxx/bin。如果這個(gè)目錄只放一兩個(gè)你常用命令完全沒必要去改 PATH直接做軟鏈接就行sudo ln -s /opt/onnxruntime/bin/onnxruntime_cli /usr/local/bin/onnxruntime_cli為何默認(rèn)選/usr/local/bin因?yàn)樗?PATH 的默認(rèn)范圍里而且是apt安裝之外的本地軟件慣例位置。把軟鏈接放進(jìn)去所有用戶、所有終端都能直接執(zhí)行同時(shí)不污染 PATH 的條目數(shù)量也方便日后通過ls -l /usr/local/bin/onnxruntime_cli快速確認(rèn)鏈接指向。做軟鏈接時(shí)要注意兩個(gè)小問題第一如果目標(biāo)已經(jīng)在/usr/local/bin存在ln 會(huì)報(bào)文件已存在需要先確認(rèn)舊文件是誰、再?zèng)Q定是否刪除后重建。第二軟鏈接不會(huì)自動(dòng)處理動(dòng)態(tài)庫依賴可執(zhí)行文件可能還依賴同一目錄下的.so文件你只鏈接了命令本體庫還是得靠第二章里的方式配好路徑。一個(gè)常見組合拳是軟鏈接解決命令入口ldconfig 解決庫路徑兩者配合才算完整。還有一個(gè)容易被忽略的細(xì)節(jié)bash 會(huì)緩存已解析的命令路徑。如果你剛做完軟鏈接在當(dāng)前終端直接執(zhí)行命令bash 可能還記著之前的command not found結(jié)果。執(zhí)行hash -r刷新一下命令緩存這個(gè)副作用就能清除。4. 實(shí)操流程以 onnxruntime 動(dòng)態(tài)庫為例完整走一遍4.1 場(chǎng)景設(shè)定與編譯運(yùn)行失敗現(xiàn)場(chǎng)假設(shè)你要在一個(gè)實(shí)際項(xiàng)目里用 ONNX Runtime 做推理從官網(wǎng)下載了針對(duì) Ubuntu 的預(yù)編譯包解壓到/opt/onnxruntime目錄結(jié)構(gòu)大致是/opt/onnxruntime/ ├── include/onnxruntime/core/session/onnxruntime_cxx_api.h ├── lib/libonnxruntime.so.1.15.1 └── lib/libonnxruntime.so - libonnxruntime.so.1.15.1你寫了一個(gè) C 推理程序 test_ort.cpp編譯命令如下g test_ort.cpp -I/opt/onnxruntime/include -L/opt/onnxruntime/lib -lonnxruntime -o test_ort編譯階段大概率是成功的因?yàn)?L指定了鏈接搜索路徑。但運(yùn)行./test_ort時(shí)報(bào)錯(cuò)./test_ort: error while loading shared libraries: libonnxruntime.so.1.15.1: cannot open shared object file: No such file or directory這個(gè)報(bào)錯(cuò)非常典型后臺(tái)原因就是運(yùn)行時(shí)鏈接器在LD_LIBRARY_PATH、ld.so.cache、默認(rèn)目錄里都沒找到這個(gè)庫。接下來按三套方案處理。4.2 三種解決方案的選擇與執(zhí)行細(xì)節(jié)方案一臨時(shí)驗(yàn)證推薦第一次先做。用LD_LIBRARY_PATH直接跑LD_LIBRARY_PATH/opt/onnxruntime/lib ./test_ort如果程序成功跑起來說明庫文件本身沒問題只是路徑?jīng)]進(jìn)搜索列表問題定位干凈利落。方案二用戶級(jí)配置。如果你是在開發(fā)機(jī)上長(zhǎng)期調(diào)試寫入~/.bashrc最方便echo export LD_LIBRARY_PATH/opt/onnxruntime/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc ./test_ort方案三系統(tǒng)級(jí)配置生產(chǎn)環(huán)境首選。創(chuàng)建 conf 文件并刷新緩存sudo tee /etc/ld.so.conf.d/onnxruntime.conf EOF /opt/onnxruntime/lib EOF sudo ldconfig ./test_ort為什么生產(chǎn)環(huán)境我會(huì)優(yōu)先選方案三因?yàn)榉?wù)通常由 systemd 托管systemd 里可以配置EnvironmentLD_LIBRARY_PATH...但每個(gè)服務(wù)單獨(dú)配容易漏而且以后換機(jī)器部署時(shí)也容易忘。把庫路徑寫進(jìn)系統(tǒng)級(jí)的/etc/ld.so.conf.d/相當(dāng)于讓整臺(tái)機(jī)器“認(rèn)識(shí)”這批庫任何用戶任何服務(wù)都能直接用最符合 Linux 的慣例。驗(yàn)證配置是否生效有三條命令# 查看緩存里是否登記了 onnxruntime ldconfig -p | grep onnxruntime # 查看程序?qū)嶋H解析到的庫路徑 ldd ./test_ort | grep onnx # 確認(rèn)鏈接指向是否正確 readelf -d ./test_ort | grep -E RPATH|RUNPATH最后那條 readelf 命令用來檢查二進(jìn)制文件編譯時(shí)是不是已經(jīng)寫死了 RPATH。如果編譯時(shí)用了-Wl,-rpath,/opt/onnxruntime/lib運(yùn)行時(shí)鏈接器會(huì)優(yōu)先從這個(gè)寫死的路徑找?guī)旒词箾]有配置系統(tǒng)路徑也能跑。但這樣做的缺點(diǎn)是路徑被焊死在文件里換個(gè)安裝目錄就失效所以大多數(shù)情況下不推薦初學(xué)者用 rpath 解決這個(gè)問題。4.3 跨機(jī)器拷貝后的 GLIBC 兼容性提醒在配置動(dòng)態(tài)庫路徑時(shí)很多人會(huì)忽略一個(gè)更麻煩的坑庫文件本身能找得到了但程序啟動(dòng)時(shí)報(bào)GLIBC_2.28 not found。Ubuntu 18.04 內(nèi)置的 glibc 是 2.27 版本如果你從別處拷貝的 .so 是在 glibc 2.28 以上的系統(tǒng)編譯的系統(tǒng)就會(huì)報(bào)這個(gè)錯(cuò)。這類問題的排查方法是用strings檢查庫文件依賴的 glibc 符號(hào)版本strings /opt/onnxruntime/lib/libonnxruntime.so.1.15.1 | grep GLIBC_ | sort -u | tail如果看到GLIBC_2.28一類的版本號(hào)Ubuntu 18.04 是跑不起來的。正確做法是找針對(duì) 18.04 編譯的預(yù)編譯包或者拿源碼在目標(biāo)系統(tǒng)上重新編譯千萬別試圖手動(dòng)升級(jí) glibc——glibc 是系統(tǒng)最底層的組件手動(dòng)替換極易讓所有命令連 ls 都執(zhí)行不了機(jī)器直接變磚。5. 常見問題速查與我的排查套路5.1 高頻問題對(duì)照表我把這些年用戶問得最多的問題整理成一個(gè)速查表按“現(xiàn)象、原因、處理”三列寫清楚。現(xiàn)象常見原因處理方式終端里能跑雙擊或桌面圖標(biāo)打不開圖形程序沒讀取 ~/.bashrc改用 /etc/ld.so.conf.d 或修改 .desktop 里的 Environmentsudo 執(zhí)行程序時(shí)找不到庫sudo 默認(rèn)清理 LD_LIBRARY_PATH使用sudo -E保留環(huán)境變量或配置系統(tǒng)級(jí) ldconfigldconfig 后仍然報(bào)找不到LD_LIBRARY_PATH 里有同名舊庫搶先或 ldconfig 沒執(zhí)行成功用ldconfig -v驗(yàn)證新目錄用ldd看實(shí)際解析路徑注意搜索優(yōu)先級(jí)新開終端生效當(dāng)前終端無效當(dāng)前 Shell 環(huán)境變量未刷新執(zhí)行source ~/.bashrc或重新打開終端PATH 改完 still command not foundhash 緩存殘留路徑順序不對(duì)軟鏈接沒建對(duì)先hash -r再用which和type -a確認(rèn)實(shí)際找到的位置程序找不到版本號(hào)為“符號(hào)鏈接后綴”的庫只做了 .so 鏈接但缺 .so.版本號(hào) 的實(shí)際文件確認(rèn) .so 真實(shí)文件存在且軟鏈接指向真實(shí)文件名5.2 從 ldd 結(jié)果里讀出問題根因碰到任何“共享庫找不到”的報(bào)錯(cuò)我的第一反應(yīng)永遠(yuǎn)是執(zhí)行l(wèi)dd ./your_program。這個(gè)命令會(huì)遞歸列出程序依賴的所有動(dòng)態(tài)庫以及它們被解析到的絕對(duì)路徑。如果某一行顯示not found問題就鎖定在這個(gè)庫上如果顯示某個(gè)路徑但你知道那個(gè)是舊版本目錄那就是優(yōu)先級(jí)問題。還有一種情況比較隱蔽庫文件存在、路徑也配置了但程序報(bào)的錯(cuò)是權(quán)限不夠。這時(shí)用ls -l查看庫文件的權(quán)限位如果有程序是在單獨(dú)用戶下運(yùn)行的比如服務(wù)賬號(hào)需要確保其他用戶對(duì)該文件有讀權(quán)限。不少生產(chǎn)事故最終定位到的是 chmod 權(quán)限問題而不是路徑配置問題。readelf -d這個(gè)命令在排查 RPATH/RUNPATH 時(shí)非常好用。它可以告訴你程序編譯時(shí)是否寫死了庫路徑避免你反復(fù)配置環(huán)境變量卻一頭霧水。我通常在給他人代碼排查時(shí)先看這個(gè)字段再?zèng)Q定是否需要查 ldconfig 緩存。5.3 一個(gè)我總結(jié)的“三步定位法”第一步判斷問題出在執(zhí)行入口還是動(dòng)態(tài)庫加載直接運(yùn)行程序如果報(bào)的是command not found那是 PATH 問題如果報(bào)的是error while loading shared libraries那是庫配置問題。這一步把兩類配置分開避免在錯(cuò)誤的方向上白費(fèi)力氣。第二步確認(rèn)庫文件是否真實(shí)存在且完整執(zhí)行file /opt/onnxruntime/lib/libonnxruntime.so.1.15.1查看架構(gòu)信息和文件類型。如果是 32 位庫裝到了 64 位系統(tǒng)或者文件本身是個(gè)損壞的空文件再改路徑配置也沒用。第三步用最小代價(jià)驗(yàn)證路徑臨時(shí)設(shè)置一次LD_LIBRARY_PATH如果你一跑就通說明路徑思路完全正確剩下的只是選擇一個(gè)持久化的方式而已。如果臨時(shí)設(shè)置都不通那要繼續(xù)排查依賴鏈比如這個(gè)庫本身又依賴了別的庫一層一層往下追。5.4 防止把配置搞炸的備份習(xí)慣在改/etc/ld.so.conf.d/之前我強(qiáng)烈建議先備份原來目錄下的所有文件。雖然正常情況下你的修改只是新增一個(gè) conf但如果你手滑覆蓋了系統(tǒng)自帶文件后果會(huì)很嚴(yán)重。我的心法是先執(zhí)行sudo cp -r /etc/ld.so.conf.d /etc/ld.so.conf.d.bak.$(date %Y%m%d)改完以后立刻用sudo ldconfig -v檢查輸出至少確認(rèn)沒有No such file or directory的提示。萬一出現(xiàn)極端情況——系統(tǒng)命令開始報(bào)錯(cuò)找不到庫了——關(guān)機(jī)前先冷靜重啟進(jìn)恢復(fù)模式把備份目錄恢復(fù)回去再執(zhí)行l(wèi)dconfig基本都能救回來。說到最后我個(gè)人在實(shí)際操作中的選型習(xí)慣很簡(jiǎn)單一次性調(diào)試用臨時(shí) LD_LIBRARY_PATH個(gè)人開發(fā)機(jī)寫 .bashrc生產(chǎn)服務(wù)器一律/etc/ld.so.conf.dldconfig。每配完一個(gè)第三方庫順手跑一遍ldd確認(rèn)依賴鏈路完整再寫進(jìn)項(xiàng)目的部署文檔里下次換新機(jī)器就能直接對(duì)照?qǐng)?zhí)行不用重新踩一遍“編譯成功但運(yùn)行失敗”的坑。這個(gè)習(xí)慣看起來有點(diǎn)繁瑣但長(zhǎng)期省下來的時(shí)間和精力遠(yuǎn)比一開始那幾分鐘多得多。