
我最早接觸 DNF 時用的還是 CentOS 系的舊版本當時從 Yum 遷移過來心里挺不以為然的這不就是把 yum 改名嗎為什么每條改系統(tǒng)的命令前面都要加 sudo后來在真實服務器上踩過幾次坑才明白sudo dnf不是儀式感而是 Linux 系統(tǒng)里以管理員權限執(zhí)行 DNF 包管理命令的標準方式。這篇文章圍繞這一句話展開把底層原因、最常用的命令組合、踩坑排查和我的個人習慣都寫出來。如果你剛入門讀完至少不會再把sudo dnf install和sudo dnf update搞混也明白了為什么查詢軟件包可以不加 sudo。如果你已經(jīng)在維護服務器后面關于倉庫鎖、GPG 校驗、history 回滾和 sudo 超時配置的內容應該能幫你在故障現(xiàn)場少繞幾圈。我會用當時執(zhí)行命令時屏幕上真正出現(xiàn)的反饋來說話盡量不寫空泛概念。1. sudo 和 DNF 是怎么組合成標準的1.1 DNF 為什么必須帶著管理員權限跑DNF 要動的是系統(tǒng)級目錄。以安裝軟件包為例它會把文件寫到/usr/bin、/usr/lib、/usr/share這些位置還會更新/var/lib/rpm和/var/lib/dnf里的軟件包數(shù)據(jù)庫。這幾個目錄普通用戶默認只有讀權限沒有寫權限所以 DNF 在檢測到非 root 身份時會拒絕執(zhí)行。這不是 DNF 故意為難你而是操作系統(tǒng)的基礎權限模型決定的。可以把它理解成手機安裝應用。普通用戶模式相當于訪客賬號你可以在自己的空間里瀏覽、試用但要把 App 裝進系統(tǒng)分區(qū)、讓所有用戶都能用必須經(jīng)過管理員授權。DNF 里大量命令的默認行為就是“改全局狀態(tài)”所以必須提權。不過有一點要記住不是所有 dnf 命令都需要 sudo。像dnf search、dnf info、dnf repoquery這類只讀元數(shù)據(jù)的操作普通用戶也能跑。真正不能少 sudo 的是那些會改變系統(tǒng)狀態(tài)的子命令比如install、remove、upgrade、autoremove、clean。這也是為什么網(wǎng)上很多教程里寫的是“以管理員權限執(zhí)行 DNF 包管理命令”而不是“所有 DNF 命令都加 sudo”。1.2 sudo 不是“切換到 root”而是“借 root 的身份執(zhí)行單條命令”sudo 做了什么它不改變你的用戶身份它只是讓當前用戶借 root 的身份去執(zhí)行某一條具體的命令。命令結束后你仍然是普通用戶。這跟su -完全不一樣。su -是直接切到 root 的交互式 shell之后所有命令都以 root 身份運行手一滑可能就把系統(tǒng)搞壞。sudo 把風險限制在單條命令里而且/var/log/secure或 journald 會記錄哪條命令、由誰執(zhí)行事后能審計。系統(tǒng)里通常 wheel 組的成員被允許執(zhí)行 sudo。安裝系統(tǒng)時創(chuàng)建的第一個用戶一般默認在 wheel 組里所以裝完系統(tǒng)直接就能用sudo dnf install。如果是在容器或最小化環(huán)境里有可能沒有安裝 sudo或者當前用戶不在 wheel 組這時才會出現(xiàn)sudo: command not found或“用戶不在 sudoers 文件中”的報錯。從實踐上看sudo dnf比su -進入 root 再執(zhí)行dnf更可靠。因為su -會加載 root 用戶的環(huán)境變量你并不清楚當前 shell 處于什么狀態(tài)而 sudo 執(zhí)行命令時走的是系統(tǒng)預設的secure_path環(huán)境相對干凈。更重要的是多人維護服務器時誰執(zhí)行了哪條 dnf 命令日志里一目了然出了問題不用互相扯皮。1.3 為什么實操習慣里都以 sudo DNF 為準社區(qū)、文檔和認證考試都推薦 sudo dnf而不是 root shell主要就是三個原因最小權限、可審計、不容易誤傷。root shell 里的每一條命令都沒有“臨時授權”的概念風險會持續(xù)累積sudo 默認只對單條命令授信即使命令寫錯了影響范圍也可控history 里以 sudo 開頭的命令容易檢查特別是多人維護服務器時審計價值很高。另外很多配置管理工具在遠程執(zhí)行命令時也走 sudo邏輯和你手動敲sudo dnf install完全一致。所以日常養(yǎng)成sudo dnf的習慣對個人、對團隊都是好事情。它不一定是最快的裝包方式但一定是最容易定位問題的裝包方式。2. sudo DNF 的日常使用場景與命令套路2.1 安裝、刪除、清理依賴最常用的三條命令日常使用中最繞不開的三條命令是sudo dnf install -y 軟件包名 sudo dnf remove -y 軟件包名 sudo dnf autoremove這里有個容易忽略的差異remove只刪除你指定的包不會自動清理它帶來的依賴autoremove會清理那些“作為依賴被自動安裝、但現(xiàn)在不再被需要”的包。舉個例子你手動裝了編譯工具鏈里的某個庫后來把主包卸載了庫會留在系統(tǒng)里。跑一次sudo dnf autoremoveDNF 會把不再被任何包依賴的庫清理掉系統(tǒng)會清爽很多。不過autoremove也不是無腦執(zhí)行。它在顯示事務摘要時會列出將要刪除的軟件包你一定要掃一眼確認沒有保留想用的包。我見過有人用sudo dnf autoremove -y把本地手動編譯安裝時臨時裝的依賴清掉了最后又重新手動裝了半天。日常升級建議用sudo dnf upgrade --refresh。在 DNF 里update和upgrade基本是同一件事upgrade是新名字。--refresh會強制刷新倉庫元數(shù)據(jù)避免明明有新版本但提示“Nothing to do”的情況。2.2 不是所有 dnf 命令都要加 sudo查詢命令對照表我整理了一個速查表適合貼在服務器終端旁邊命令是否需要 sudo說明dnf search不需要按包名或描述搜索dnf info不需要查看包詳情、大小、倉庫來源dnf list installed不需要列出已安裝包dnf repoquery不需要按文件路徑、依賴關系反向查包dnf provides /usr/bin/xxx建議查某個命令屬于哪個包dnf install需要安裝軟件包dnf remove需要卸載軟件包dnf upgrade需要升級系統(tǒng)軟件dnf autoremove需要清理不再需要的依賴dnf clean需要清理緩存dnf history undo需要回滾歷史事務表格里有一個例外情況如果本機從未運行過 dnf 查詢普通用戶執(zhí)行dnf search時可能會因為緩存目錄權限或自動下載元數(shù)據(jù)失敗而報錯。這種時候我第一次通常先執(zhí)行sudo dnf makecache把緩存準備好后面再用普通用戶查詢就很順暢。2.3 常用參數(shù)怎么選才不會翻車DNF 的參數(shù)很多但真正值得掌握的也就那么幾個。-y表示自動回答 yes。腳本里必須加否則會卡在確認提示手動安裝時反而不建議加因為事務摘要里可能出現(xiàn)“某個包會把系統(tǒng)里另一個包替換”的警告提前發(fā)現(xiàn)比事后回滾省事。--enablerepo和--disablerepo是臨時啟用或禁用倉庫。比如sudo dnf install --enablerepoextra 軟件包名這樣只對當前命令生效不會永久改配置。排查倉庫問題時特別有用可以做到“只測一個變量”。--downloadonly配合--downloaddir可以只下載不安裝sudo dnf install --downloadonly --downloaddir/tmp/pkg 軟件包名下載下來的 RPM 包可以拷貝到內網(wǎng)機器安裝。注意跨發(fā)行版小版本之間不一定兼容建議同版本系統(tǒng)之間使用。--allowerasing是一個要小心的參數(shù)。當安裝的包會覆蓋系統(tǒng)已有包時DNF 默認拒絕加上它才允許刪除沖突包。某些第三方源確實需要但別默認加上因為它可能把系統(tǒng)組件替換掉而且不一定會提前警告你。--nogpgcheck我?guī)缀醪挥?。這個參數(shù)會跳過 RPM 的 GPG 簽名驗證等于把包來源的安全檢查關掉了。后面講 GPG 問題時會細說。2.4 什么時候不要亂加 sudo很多人養(yǎng)成“DNF sudo”的慣性連dnf list installed這種只讀命令也加 sudo。壞處不是命令錯而是它會以 root 身份執(zhí)行緩存目錄/var/cache/dnf或用戶級配置可能一下子變成 root 所有導致普通用戶后續(xù)查詢要反復提權反而讓日常操作更麻煩。查詢命令不需要管理員權限就別加。還有一類操作也要區(qū)分安裝本地 RPM 包的正確姿勢是sudo dnf install ./package.rpm不是sudo dnf install ./package.sh。DNF 不會因為文件后綴不同就把腳本執(zhí)行掉但 RPM 包自帶的安裝腳本確實會以 root 身份運行所以本地包來源必須可靠。如果你是從不明網(wǎng)站下載的 RPM即使能裝也別裝。3. 實操過程從一條 sudo DNF 命令看完整安裝流程3.1 動手之前先確認這幾項在干凈環(huán)境里第一次使用 DNF 我習慣先跑這幾條cat /etc/os-release command -v dnf || echo dnf not found dnf --version groups sudo -lcat /etc/os-release確認發(fā)行版和版本號command -v dnf看 DNF 是否在 PATH 里dnf --version看 DNF 自身版本groups確認當前用戶在不在 wheel 組sudo -l看當前用戶到底被允許執(zhí)行哪些 sudo 命令。如果系統(tǒng)沒有 sudo先su -進入 root再執(zhí)行dnf install -y sudo usermod -aG wheel 你的用戶名然后退出 root 并重新登錄。注意usermod修改的是擴展組成員關系當前登錄會話不會立即生效必須重新登錄或者至少重新打開一個登錄 shell。否則你依然會看到“用戶不在 sudoers 文件中”。3.2 一次安裝命令的完整執(zhí)行流程拿最常見的sudo dnf install -y inotify-tools舉例。屏幕上的輸出看起來是一堆進度條但背后其實經(jīng)歷了七個階段sudo 要求輸入密碼驗證通過后進入默認的 15 分鐘緩存期DNF 讀取/etc/dnf/dnf.conf和/etc/yum.repos.d/下的倉庫配置如果倉庫元數(shù)據(jù)緩存過期會去下載各倉庫的元數(shù)據(jù)構建事務由 libsolv 解析依賴關系顯示將要安裝的包列表和依賴清單下載 RPM 到/var/cache/dnf然后做 GPG 簽名校驗通過 RPM 事務把軟件包解壓到系統(tǒng)目錄更新 RPM 數(shù)據(jù)庫。新手最容易忽略的是第 4 步和第 6 步。第 4 步的依賴解析保證你裝的包所依賴的庫也會被裝上第 6 步的 GPG 校驗保證 RPM 沒被篡改。如果這兩個步驟出錯報錯信息會明確寫出來比如Public key for xxx is not installed或“依賴沖突”。這類問題我在第 4 部分會專門講。3.3 幾個關鍵參數(shù)的實戰(zhàn)用法用一個實際場景來說。某臺服務器上系統(tǒng)自帶的軟件版本比較老我想臨時試試倉庫里的更新版本但不想影響默認倉庫。命令可以寫成sudo dnf install --disablerepobase --enablerepoupdates-testing -y 軟件包名這樣只影響當前命令不會污染系統(tǒng)全局倉庫配置。如果安裝時提示“某個包將被其他包替換”DNF 會先輸出事務摘要這時你需要停下來看提示再決定要不要加--allowerasing。離線場景也很常見。先在聯(lián)網(wǎng)機器上下載sudo dnf install --downloadonly --downloaddir/tmp/pkg 軟件包名然后把整個目錄拷貝到內網(wǎng)機器執(zhí)行sudo dnf install /tmp/pkg/*.rpmDNF 會嘗試解析本地 RPM 的依賴關系。如果缺少依賴它會提示你還要先裝哪些包這種反向定位方式比一個個手動試要高效得多。3.4 跨版本升級sudo dnf system-upgrade 的完整流程跨大版本升級和平時sudo dnf upgrade不一樣。Fedora 系的標準流程是這樣sudo dnf upgrade --refresh sudo dnf install dnf-plugin-system-upgrade sudo dnf system-upgrade download --releasever新版本號 sudo dnf system-upgrade reboot第一步是確保當前系統(tǒng)補丁齊全第二步安裝升級插件第三步把新版本所有 RPM 下載到本地并做依賴檢查第四步會立即重啟進入升級過程。如果download階段報錯先執(zhí)行sudo dnf system-upgrade clean清理臨時數(shù)據(jù)再重新下載。不要帶著報錯強行 reboot很可能會進不去系統(tǒng)??绨姹旧壡爸辽僮鋈聜浞葜匾獢?shù)據(jù)、確認第三方倉庫是否兼容新版本、暫時停止自動更新服務??绨姹旧壊幌裥“姹旧壙梢噪S便回滾下載階段檢查的依賴問題最好盡早暴露。我個人的經(jīng)驗是如果機器上有生產(chǎn)業(yè)務先看變更計劃再挑維護窗口執(zhí)行別在業(yè)務高峰期碰系統(tǒng)升級。4. 常見問題與排查技巧實錄4.1 權限類問題為什么加了 sudo 還是提示沒有權限最經(jīng)典的報錯是user is not in the sudoers file或者sudo: command not found。排查順序其實是固定的groups看當前用戶是否在 wheel 組sudo -l看具體授權用visudo檢查/etc/sudoers有沒有語法錯誤如果 sudoers 被改壞從 root 會話中運行visudo修復.這里必須強調改 sudoers 千萬別直接用普通編輯器要使用visudo。它保存時會做語法檢查語法錯誤會讓所有 sudo 命令失效恢復起來很麻煩。我見過有人把某一行多寫了一個字符結果整臺服務器所有非 root 用戶都無法提權最后只能從救援模式進入系統(tǒng)修復。另外一種“加了 sudo 還是 Permission denied”的情況常見于容器或特殊系統(tǒng)里。很多容器鏡像默認沒有 sudo直接以 root 運行 dnf 是正常的。但容器里的 root 本身已經(jīng)被隔離范圍相對可控所以不必照搬物理機習慣。4.2 倉庫鎖Another app is currently holding the dnf lock使用 DNF 時最煩的提示之一就是這個。后臺通常是 PackageKit 自動刷新、軟件商店更新或者上一個 dnf 進程被 CtrlC 中斷后鎖沒有自動釋放。先看有沒有進程還在跑ps aux | grep -E dnf|packagekit systemctl status packagekit sudo systemctl stop packagekit如果查了半天沒有進程再去看鎖文件。DNF 鎖一般在/var/cache/dnf下的.lock文件或/var/lib/dnf里。確認沒有相關進程后可以手動刪除鎖文件恢復執(zhí)行。但刪除鎖只是恢復機制真正要做的是搞清楚為什么鎖卡住了。我遇到過一次是某個倉庫源響應極慢dnf 進程一直在等網(wǎng)絡看起來像死鎖其實是網(wǎng)絡連接超時的問題。后來換了一個可達性更好的源鎖問題自動消失。4.3 鏡像源與元數(shù)據(jù)緩存別一上來就 clean all換源之后常見報錯是Metadata file does not match checksum或者Cannot retrieve metalink for repository。原因多是鏡像同步不完整或者本地緩存已經(jīng)畸形。正確處理順序是sudo dnf clean all sudo dnf makecache注意clean all會把所有倉庫元數(shù)據(jù)刪掉下次命令會重新下載所以不要把它當日常清潔命令。平時刷新緩存用sudo dnf makecache就夠了升級前用sudo dnf upgrade --refresh也足夠。如果清完緩存還是報錯問題多半出在/etc/yum.repos.d/里的倉庫配置。用dnf repolist看當前啟用的倉庫再臨時禁用有問題的倉庫測試sudo dnf install --disablerepobadrepo 軟件包名不要一上來就刪倉庫文件先禁用診斷確認根因再處理這樣可回退空間大很多。4.4 GPG 驗證失敗怎么辦報錯Public key for xxx is not installed或者The GPG signature of xxx is invalid時DNF 默認拒絕安裝。這是防止軟件包被篡改的關鍵機制不要輕易繞過。正確做法是導入對應倉庫的官方 GPG 公鑰。發(fā)行版官方包的 key 一般可以從系統(tǒng)自帶位置找到第三方倉庫會在文檔里公布指紋。你可以先執(zhí)行rpm -q gpg-pubkey看已經(jīng)導入的公鑰列表再決定要不要導入。如果為了圖快直接加--nogpgcheck相當于告訴系統(tǒng)“不管這個包是誰簽的一律裝”跟把安全門拆了沒區(qū)別。尤其是從不明來歷的源下載 RPM 時--nogpgcheck會讓系統(tǒng)毫無抵抗能力。這個參數(shù)可以當成一次性逃生門但絕不能放進日常腳本。每次看到網(wǎng)上有人把--nogpgcheck寫進安裝教程我都會提醒一句這是不負責任的做法。4.5 依賴沖突與找不到軟件包“沒有可用軟件包”通常不是包不存在而是所在倉庫未啟用或者包名拼錯了。先搜索dnf search 關鍵字 dnf provides /usr/bin/某個命令第二句非常有用它告訴你某個文件屬于哪個包。比如提示缺少/usr/bin/xx但你不記得包名用dnf provides /usr/bin/xx一下就能查出來。真正的依賴沖突會看到類似package A conflicts with B provided by C的信息。這時先看沖突原因可能是兩個源各自提供同名包。用dnf repoquery --whatprovides 包名看來源再決定禁用哪個倉庫。--allowerasing能解決某些替換但如果把它當成默認操作遲早會誤刪系統(tǒng)組件。相比之下我更推薦使用包組而不是手動裝一堆包sudo dnf group install Development Tools包組內部的依賴已經(jīng)被維護者整理過比手動一個個裝省心回滾時也更清晰。5. 實操中的幾個個人習慣5.1 在腳本里用 sudo -n 避免卡在密碼輸入自動化腳本里最怕的場景就是執(zhí)行到一半卡在密碼輸入。sudo 默認在無終端環(huán)境下會直接失敗但交互腳本可能會有意外。給 sudo 加-n可以保證如果需要密碼就立即退出而不是掛在那里等輸入。sudo -n dnf install -y 軟件包名 || echo 需要手動密碼這個習慣能讓定時任務更可靠也方便報錯時直接看到哪一步失敗。如果腳本需要自動提權可以給特定指令配置 NOPASSWD但別把所有 sudo 都設成免密。給 dnf 本身開免密還可以接受給所有命令開免密等于把 sudo 的安全邊界拆了。5.2 把 sudo 自動提權時間調短一點sudo 默認記住密碼一段時間Fedora 系一般是 15 分鐘。個人桌面足夠服務器或共享機器上我習慣調短防止有人趁你離開時的緩存窗口執(zhí)行管理員命令。修改方法是用sudo visudo找到或添加Defaults timestamp_timeout5單位是分鐘。調成 5 以后超過 5 分鐘沒執(zhí)行 sudo再輸入下一條又要密碼。某些運維場景想完全取消緩存可以設 0但那樣每次命令都輸密碼適合安全要求高的環(huán)境。再次提醒必須用visudo修改不要直接用vi改/etc/sudoers。語法錯誤會讓你連 sudo 都用不了到時候只能從 root 會話修復。5.3 善用 dnf history 做事務回滾DNF 把每次安裝、刪除、升級都記錄成一個事務可以用sudo dnf history查看。如果某次安裝導致系統(tǒng)出現(xiàn)問題想回到之前狀態(tài)執(zhí)行sudo dnf history list sudo dnf history info 事務ID sudo dnf history undo 事務IDundo會嘗試反向執(zhí)行這個事務比如把安裝的包移除、把升級的包降級。但有一點必須說清楚它不一定能完全恢復到一模一樣的狀態(tài)因為某些配置文件在升級后會被修改undo不負責還原配置。所以涉及配置改動時還是要自己檢查/etc下的變更??绨姹旧壓笕绻到y(tǒng)進不了圖形界面可以用舊內核啟動再通過sudo dnf history rollback回到升級前的事務。在沒有備份的情況下這是最后一根稻草。5.4 一個可以立刻用起來的小技巧sudo 別名與 PATH 問題最后說一個能減少敲錯概率的小技巧在~/.bashrc里加別名。alias updatesudo dnf upgrade --refresh alias installsudo dnf install -y alias removesudo dnf remove -y但有一個坑sudo 默認會重置 PATH如果某個命令裝在/usr/local/binsudo 通常能找到但如果自己裝了一個自定義腳本在/opt/bin通過 sudo 調用時可能找不到。解決辦法是用sudo -E保留當前環(huán)境或者直接用絕對路徑sudo /opt/bin/xxx不要默認 root 用戶的 PATH 和普通用戶完全一致。我之前就遇到過明明包裝好了加 sudo 卻提示命令不存在實際是 PATH 差異造成的。我自己在服務器上很少直接開 root 終端習慣就是把操作拆成一條條 sudo 命令。這樣出了問題翻 history 也知道當時執(zhí)行過什么。如果你也想調整自己的習慣從今天開始把dnf install改成sudo dnf install把dnf upgrade改成sudo dnf upgrade --refresh就已經(jīng)邁出一大步了。