SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

如何修復 apt 來源重複與 deb822 檔案

apt update 顯示「Target is configured multiple times」?找出重複的 .list 與 .sources 檔案,保留一份,即可恢復乾淨的更新結果。

重複 apt 來源錯誤的含義

apt 來源重複表示同一個軟體套件儲存庫在兩個不同檔案中宣告了兩次,APT (advanced package tool) 找到了這兩份宣告。在 Ubuntu 24.04 及更新版本中,幾乎總是因為第三方安裝指令碼寫入了舊式單行 .list 檔案,而相同儲存庫的 deb822 .sources 檔案已經存在於磁碟上。沒有任何檔案損毀,也沒有套件面臨風險。刪除其中一份宣告後,訊息就會消失。

這是人們常貼到搜尋框中的那一行:

W: Target Packages (stable/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/docker.list:1 and /etc/apt/sources.list.d/docker.sources:1

從結尾開始讀。兩個檔案各自包含行號,並宣告相同的內容。Target Packages 是 apt 下載的索引,用來得知儲存庫提供哪些套件;stable/binary-amd64/Packages 則指定該索引涵蓋的元件 (stable) 與架構 (amd64)。因此,apt 告訴你 stable 元件的 amd64 索引已在 docker.list 的第 1 行設定一次,也在 docker.sources 的第 1 行再次設定。

在 apt 3.0 及更新版本中,也就是 Ubuntu 25.04 以後的版本與 Debian 13,相同訊息會以 Warning: 開頭,而不是 W:。前綴後面的文字相同。

這個警告屬於較輕微的情況。apt 會合併這兩份宣告,更新仍會執行,因為兩份宣告描述的是使用相同金鑰的相同封存庫。嚴重的情況則會停止所有操作:

E: Conflicting values set for option Signed-By regarding source https://download.docker.com/linux/ubuntu/ noble: /usr/share/keyrings/docker-archive-keyring.gpg != /etc/apt/keyrings/docker.asc
E: The list of sources could not be read.

這裡 apt 會拒絕執行,因為兩份宣告為同一個封存庫指定了不同的簽署金鑰。它會合併兩份完全相同的宣告,但不會在兩個 Signed-By 值之間選擇,因為選錯金鑰就表示使用封存庫擁有者從未用來簽署的金鑰驗證套件簽章。因此,apt 完全不會讀取任何來源。在你手動編輯檔案前,apt update 與 apt install 都會因為相同的兩行而失敗。

重複來源的形成原因

這兩種格式分別儲存在副檔名不同的檔案中,因此檔案系統不會阻止兩者同時存在。apt 會在較晚的階段才注意到重疊,因為它必須將每個來源檔案展開成預計下載的索引目標清單。在此之前,docker.list 和 docker.sources 是兩個互不相關的檔案。

以下 4 種常見事件會產生這組檔案:

  • 廠商安裝指令碼,或從舊文章複製的命令,使用 tee 行寫入 /etc/apt/sources.list.d/vendor.list。
  • 廠商後續提供自己的套件,其中包含 /etc/apt/sources.list.d/vendor.sources,並自動替你安裝。
  • Ubuntu 24.04 及更新版本中的 add-apt-repository 會寫入 deb822 格式的 .sources 檔案,因此你過去手動以 .list 新增的 PPA(個人套件檔案庫)會以 .sources 的形式重新出現。
  • 發行版升級將發行版本身的來源改寫為 deb822 格式,但保留你手寫的 .list 檔案,讓它與這些檔案並存。

每條路徑單獨看都合理。當其中兩種情況在同一台主機上發生時,就會形成重複來源,而且通常相隔數個月。

兩種格式並列比較

舊格式每個套件庫使用一行表示,所有欄位都依位置判讀。

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable

順序固定:先是類型(二進位套件使用 deb,原始碼套件使用 deb-src),接著是方括號中的選項、套件庫的 URI(統一資源識別碼)、suite,最後是一個以上的 component。由於欄位意義取決於位置,空格放錯位置就會改變 apt 的解析結果。

deb822 會以具名欄位的 stanza 表達相同內容。這個名稱來自 RFC 822,也就是 Debian 已用於套件控制檔的郵件標頭格式。

Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc

套件庫相同、金鑰相同,沒有新增內容。對應關係是直接的:deb 會變成 Types,套件庫位址會變成 URIs,suite 會變成 Suites,components 會變成 Components;每個方括號選項則各自成為一個欄位,因此 signed-by= 會變成 Signed-By:,而 arch= 會變成 Architectures:。

每個欄位名稱都使用複數,因為每個欄位都接受以空格分隔的清單。一個 stanza 中的 Suites: noble noble-updates noble-backports 會取代 3 個分開的 deb 行。空白行會結束一個 stanza,因此單一 .sources 檔案可以包含多個套件庫。deb822 也能承載單行格式不易處理的設定:使用 Enabled: no 停用套件庫、設定 Trusted 和 Check-Valid-Until,以及將 inline key 直接貼入 Signed-By;其中每一行前方都要縮排 1 個空格,空白行則寫成單獨一個句點。

各檔案的位置

  • /etc/apt/sources.list:原本的單一檔案。在 Ubuntu 24.04 及更新版本中,通常為空檔案,或只包含指向新位置的註解。
  • /etc/apt/sources.list.d/*.list:每行一筆項目,通常每個軟體存放庫使用一個檔案。
  • /etc/apt/sources.list.d/*.sources:deb822 區塊。Ubuntu 24.04 及更新版本會將發行版內建的軟體存放庫放在此處的 ubuntu.sources。
  • /etc/apt/keyrings/:存放您新增的金鑰。/usr/share/keyrings/ 存放由套件提供的金鑰。

apt 只會讀取結尾為 .list 或 .sources 的檔案,且檔名只能包含字母、數字、底線、連字號和句點。使用其他副檔名的檔案會遭略過並顯示通知,這點會影響下方的修正方法。

找出重複的項目

先列出目錄內容:

ls -l /etc/apt/sources.list.d/
-rw-r--r-- 1 root root  195 Aug  3 09:12 docker.list
-rw-r--r-- 1 root root  254 Aug  9 14:40 docker.sources
-rw-r--r-- 1 root root 2683 Jun 11 08:02 ubuntu.sources

兩個檔案具有相同的主檔名但副檔名不同,通常就是成對的檔案,但不要只相信檔名。請讀取檔案內容,因為重複項目可能藏在任何檔名的檔案中:

grep -rn -E '^(deb |deb-src |Types:|URIs:|Suites:|Signed-By:)' /etc/apt/sources.list /etc/apt/sources.list.d/
/etc/apt/sources.list.d/docker.list:1:deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable
/etc/apt/sources.list.d/docker.sources:1:Types: deb
/etc/apt/sources.list.d/docker.sources:2:URIs: https://download.docker.com/linux/ubuntu
/etc/apt/sources.list.d/docker.sources:3:Suites: noble
/etc/apt/sources.list.d/docker.sources:6:Signed-By: /etc/apt/keyrings/docker.asc

這一對是具有相同主機與相同套件組的兩個項目。兩者都指向 https://download.docker.com/linux/ubuntu 與套件組 noble,因此是同一個套件庫的重複設定。兩者的 Signed-By 路徑也不一致,這正是稍早顯示 Conflicting values 錯誤的原因。

此步驟請使用 grep,不要使用 apt 命令。apt 已因衝突而停止時,也無法列出來源,因此 apt-cache policy 只會輸出相同的錯誤,而不是你要的結果。

修正方式:保留 deb822 檔案,移除舊格式檔案

保留 .sources 檔案。這是目前 apt 工具寫入的格式,也是 Debian 與 Ubuntu 未來採用的格式。刪除任何檔案前,先確認以下兩個關鍵路徑中,哪些路徑存在於磁碟上:

ls -l /etc/apt/keyrings/ /usr/share/keyrings/ | grep -i docker
-rw-r--r-- 1 root root 4813 Aug  9 14:40 docker.asc

只有 /etc/apt/keyrings/docker.asc 存在,因此 deb822 檔案中的內容才是正確狀態,而 .list 檔案指向已移除的金鑰。如果準備保留的檔案指向不存在的金鑰,請先將可運作的路徑寫入該檔案,再刪除另一個檔案。

請將舊格式檔案移出該目錄,不要直接刪除:

sudo mkdir -p /root/apt-sources-backup
sudo mv /etc/apt/sources.list.d/docker.list /root/apt-sources-backup/
sudo apt update

也可以將檔案重新命名為 docker.list.bak 並留在原處,因為 apt 會忽略未知的副檔名,但之後每次執行 apt 都會顯示以下訊息:

N: Ignoring file 'docker.list.bak' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extension

將檔案移到其他位置可避免畫面顯示該通知,同時保留備份。完成後,正常的 apt update 應如下所示,且不應有任何列出兩個檔案的內容:

Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 https://download.docker.com/linux/ubuntu noble InRelease [48.8 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 175 kB in 1s (146 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

現在確認儲存庫仍可正常使用:

apt-cache policy | grep download.docker.com
 500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     origin download.docker.com

如果供應商的文件仍假設使用單行檔案,也可以保留該檔案,改為刪除 .sources 檔案。無論採用哪種方式,都必須遵守同一項規則:同一個 archive 與 suite 只能由一個檔案宣告。

為什麼損壞的第三方來源會使 apt update 卡住

相鄰的另一種錯誤看起來不同,但根本原因相同:apt 無法使用某個第三方來源。第一種情況是缺少金鑰:

Err:5 https://download.docker.com/linux/ubuntu noble InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.

Signed-By 欄位遺失,或指向的檔案不是可用的金鑰,因此 apt 無法驗證封存檔的 InRelease 檔案簽章。接著,apt 會捨棄整個儲存庫,而不是信任無法驗證的套件清單。請直接檢查金鑰檔案:

ls -l /etc/apt/keyrings/docker.asc
gpg --show-keys /etc/apt/keyrings/docker.asc

有效的金鑰會列出包含金鑰 ID 的 pub 行,以及標示供應商名稱的 uid 行。gpg: no valid OpenPGP data found. 表示該檔案根本不是金鑰。通常這代表下載結果是錯誤頁面,因為金鑰 URL 已經變更。請重新取得金鑰、檢查檔案,然後執行 apt update。

第二種情況會在版本升級後出現:

Err:6 https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky InRelease
  404  Not Found [IP: 10.0.0.80 443]
E: The repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky Release' does not have a Release file.

PPA 沒有針對該套件版本發佈任何內容,因此伺服器上不存在該路徑,請求會回傳 404。其他儲存庫仍可更新,現有的套件也不受影響。不過,這次執行會以非零狀態結束,因此任何檢查 apt update 結束狀態的指令碼,每次執行都會回報失敗。這就是為什麼在已設定 無人值守安全性升級 的主機上,應清除失效來源:真正的錯誤往往會被每日雜訊掩蓋。供應商的安裝指令碼會遇到這兩種情況,這也是為什麼大多數 Ubuntu 上的 Tailscale 安裝錯誤,最後都發現是指令碼未寫入金鑰環,或封存檔不支援該版本代號。

停用單一來源而不影響其他來源

對於 deb822 檔案,請在該段落加入一個欄位並儲存:

Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu
Suites: plucky
Components: main
Signed-By: /etc/apt/keyrings/ondrej-php.asc
Enabled: no

apt 手冊建議使用這種方式,而不是將該段落的每一行加上註解。這也比較容易復原。對於單行檔案,請在該行開頭加入 #。無論採用哪種格式,將檔案移出 /etc/apt/sources.list.d/ 也有效;如果該套件庫已永久移除,應選擇這個方式。

再次執行 sudo apt update。該套件庫的 Err: 區塊會消失,結束狀態也會回到 0。您可以在下一行使用 echo $? 檢查。

切勿使用 sudo rm /etc/apt/sources.list.d/* 修復損壞的來源。在 Ubuntu 24.04 及更新版本中,這會刪除 ubuntu.sources。該檔案包含發行版自己的套件庫,因此 apt 會完全沒有套件清單,並對明顯存在的軟體回報 E: Unable to locate package curl。如果您已經執行該指令,請寫回檔案:

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

將檔案儲存為 /etc/apt/sources.list.d/ubuntu.sources,並將 noble 替換為您從 lsb_release -cs 取得的發行版本名稱,然後執行 sudo apt update。

將舊版 .list 檔案轉換為 deb822

截至 2026 年 8 月,apt 3.0 及更新版本已提供轉換工具。Debian 13 已包含此工具,Ubuntu 25.04 及之後的所有版本也都包含,包括 26.04。先檢查版本,再執行:

apt --version
sudo apt modernize-sources

此工具會將 /etc/apt/sources.list.d/ 下的單行檔案改寫為 deb822 .sources 檔案。請先閱讀輸出內容,再自行列出該目錄,並執行 apt update,確認結果無誤後再採用。Ubuntu 24.04 隨附較舊的 apt,沒有這個子命令;在該版本中,該命令會回應 E: Invalid operation modernize-sources。在此版本中,請依照上述欄位對應手動轉換。

目前轉換並非必要,因為 apt 仍會讀取這兩種格式。不過,如果伺服器預計長期使用,仍值得進行轉換,因為現在所有會寫入來源設定的工具都會寫入 deb822,而只包含 .sources 檔案的主機不會產生這類重複項目。

讓伺服器上的第三方套件來源保持整潔

第三方套件庫是伺服器中最容易老化的部分。每個套件庫都代表其他人承諾會持續為你的 Ubuntu 發布版本提供套件,而升級發布版本時,會在同一天檢驗這些承諾是否仍然有效。

  • 只有在發行版套件無法滿足需求時,才新增第三方套件庫。單純的 Ubuntu 24.04 上的 LAMP 堆疊不需要第三方來源:Ubuntu 套件庫已包含其使用的所有套件,並在該發布版本的支援期間提供安全性更新。
  • 將金鑰存放在 /etc/apt/keyrings/,每個供應商使用一個檔案,權限設為 644。未具特權的 _apt 使用者會負責下載,且必須讀取金鑰;因此,若金鑰檔案只有 root 可讀,從該套件庫擷取套件時每次都會發生權限錯誤。
  • 在每個來源設定區塊中,讓 Signed-By 指向該確切檔案。若金鑰存放在 /etc/apt/trusted.gpg 或 /etc/apt/trusted.gpg.d/,該金鑰就會受信任於這台伺服器上的所有套件庫。這表示多年前加入的供應商金鑰,可能會驗證來自任何來源的套件。
  • 升級發布版本前,檢查套件來源,確認每個供應商已經為即將升級到的套件版本代號發布套件。

舊版全域金鑰環中的金鑰會在每次更新時顯示警告:

W: https://download.docker.com/linux/ubuntu/dists/noble/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

將該單一金鑰匯出到獨立檔案,然後讓來源設定區塊指向該檔案:

gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --export 7EA0A9C3F273FCD8 | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/docker.gpg

在套件庫的來源設定區塊中加入 Signed-By: /etc/apt/keyrings/docker.gpg,然後執行 sudo apt update。當沒有任何套件庫再依賴舊版金鑰環後,警告就會停止;接著即可使用 sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --delete-key 7EA0A9C3F273FCD8 移除該項目。

還有一個習慣最能避免麻煩。do-release-upgrade 會在升級期間停用第三方來源,且升級完成後仍維持停用狀態;之後手動逐一重新啟用時,正是最容易建立重複宣告的時機。開始前先閱讀Ubuntu 24.04 升級至 26.04 的指南,並記下仍需要的套件庫。對於剛建立的機器,修正套件來源最省事的時機,是在新 VPS 上的前 10 分鐘內,因為此時伺服器上只有 Ubuntu 隨附的來源。

FAQ

為什麼 apt 會說某個 target 設定了多次?

因為 /etc/apt/sources.list.d/ 下的兩個檔案宣告了相同的 repository、suite 和 component。訊息會列出兩個檔案及其行號,例如 docker.list:1 和 docker.sources:1。apt 會將它們合併後繼續執行,因此更新本身仍可正常完成。不過仍應清除重複設定:只要兩個檔案指定不同的 signing key,apt 就會以 E: Conflicting values set for option Signed-By 終止,拒絕讀取任何來源,這也會導致 apt install 無法執行。

我應該保留 .list 檔案還是 .sources 檔案?

保留 .sources 檔案。deb822 是 add-apt-repository 在 Ubuntu 24.04 及更新版本中寫入的格式。每個設定使用一個具名欄位,而不是將文字依位置放在方括號中,也是各發行版的發展方向。刪除 .list 檔案前,請先使用 ls -l /etc/apt/keyrings/ 確認 .sources 檔案中的 Signed-By 路徑指向現有的 key。請將舊檔案移出 /etc/apt/sources.list.d/,不要在該目錄內重新命名,因為殘留的 .bak 名稱會讓 apt 每次執行時都顯示忽略檔案的通知。

如何停用某個 apt repository,但不將其移除?

在 deb822 .sources 檔案的 stanza 中加入 Enabled: no。在單行格式的 .list 檔案中,則在該行開頭加入 #。無論採用哪種方式,之後都執行 sudo apt update,該 repository 的 Err: 區塊就會消失。當第三方 repository 尚未提供適用於 Ubuntu 發行版本的套件,且其 404 導致 apt update 以非零狀態結束時,這是正確的處理方式。

單行 sources.list 格式會被淘汰嗎?

這種格式已棄用,但尚未移除。apt 仍會讀取 .list 檔案,且在很長一段時間內都會繼續支援,因此伺服器不會在明天突然失效。新的工具會寫入 deb822:Ubuntu 24.04 及更新版本會將發行版 repository 保留在 /etc/apt/sources.list.d/ubuntu.sources,而 add-apt-repository 會寫入 .sources 檔案。在 apt 3.0 及更新版本中,sudo apt modernize-sources 會轉換現有的檔案。

#apt#ubuntu#deb822#package-management#troubleshooting