不曉得各位有在使用ROS的大家,是否在最近幾個月在執行 sudo apt update
後,看到一堆類似下面密密麻麻的錯誤和警告訊息呢?
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.ros.org/ros/ubuntu focal InRelease: The following signatures were invalid: EXPKEYSIG F42ED6FBAB17C654 Open Robotics <info@osrfoundation.org>
W: Failed to fetch http://packages.ros.org/ros/ubuntu/dists/focal/InRelease The following signatures were invalid: EXPKEYSIG F42ED6FBAB17C654 Open Robotics <info@osrfoundation.org>
W: Some index files failed to download. They have been ignored, or old ones used instead.
簡單來說:用來簽署 ROS 軟體包的 GPG 公鑰,已經在 2025 年 6 月 1 日正式過期了。
GPG (GNU Privacy Guard) 金鑰的功能,就像是軟體包的「數位簽章」或「官方印章」。當你透過 apt 從 ROS 的官方伺服器下載軟體時,你的系統會用預存的公鑰來驗證這個軟體包是不是真的由 Open Robotics 官方發布、且在傳輸過程中沒有被竄改。
這是一個行之有年的標準安全措施。然而,金鑰本身也和 SSL 憑證一樣,具有時效性。舊的 F42ED6FBAB17C654 這把金鑰到期後,apt 就無法再用它來驗證軟體包的簽章,因此拋出 EXPKEYSIG (Expired Key Signature) 的錯誤,並拒絕更新索引。
為了解決這個問題,並為未來的金鑰輪替做準備,ROS 官方推出了全新的金鑰管理方式。過去我們需要手動下載金鑰並用 apt-key add
加入,現在官方將金鑰和軟體來源設定打包成了一個專門的 .deb
軟體包。
這種新方法有兩大好處:
安全性更高:遵循了 Debian 官方建議的最佳實踐,避免使用已棄用的 apt-key
。
管理更方便:未來金鑰再次過期時,我們只需要透過 apt 更新這個管理包即可,無需再手動操作,真正做到一勞永逸。
以下是針對 Ubuntu/Debian 系統的解決步驟:
移除舊的、已過期的金鑰
首先,我們需要將系統中舊的 ROS 金鑰刪除,避免產生衝突。請打開你的終端機,執行以下指令:
sudo apt-key del "F42ED6FBAB17C654"
如果系統回報找不到該金鑰,也沒關係,代表你的系統中本來就沒有這把舊鑰匙,可以直接進行下一步。
安裝新的金鑰管理包
接下來,根據你使用的 ROS 版本,安裝對應的管理包。
如果你是 ROS 1 的使用者 (例如 Noetic):
請安裝 ros-apt-source
這個包。
sudo apt update
sudo apt install ros-apt-source
如果你是 ROS 2 的使用者 (例如 Humble, Iron):
請安裝 ros2-apt-source
這個包。
sudo apt update
sudo apt install ros2-apt-source
安裝過程中,這個軟體包會自動幫你:
新增正確的 ROS 軟體來源列表 (.list 檔案)。
將新的 GPG 簽署金鑰放置到正確的位置 (/usr/share/keyrings/
)。
更新並驗證
完成上一步後,你的系統就已經配置好了新的金鑰與來源。現在,再次執行更新指令來驗證成果:
sudo apt update
如果終端機順利地完成更新,沒有再出現 EXPKEYSIG F42ED6FBAB17C654 的錯誤訊息,那麼恭喜你,問題已經完美解決!你現在可以正常地安裝或更新任何 ROS 相關的軟體包了。
為了讓大家更方便,這裡提供一個簡單的 Bash Script,它會自動偵測你的環境並執行上述所有修復步驟。
使用方法:
fix_ros_key.sh
。chmod +x fix_ros_key.sh
。sudo ./fix_ros_key.sh
。#!/bin/bash
# --- Colors for better output ---
C_RESET='\033[0m'
C_RED='\033[0;31m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[0;33m'
C_BLUE='\033[0;34m'
# --- Utility Functions ---
info() { echo -e "${C_BLUE}[INFO] $1${C_RESET}"; }
success() { echo -e "${C_GREEN}[SUCCESS] $1${C_RESET}"; }
warn() { echo -e "${C_YELLOW}[WARNING] $1${C_RESET}"; }
error() { echo -e "${C_RED}[ERROR] $1${C_RESET}"; }
# --- Configuration ---
OLD_KEY_ID="F42ED6FBAB17C654"
NEW_KEY_URL="https://raw.githubusercontent.com/ros/rosdistro/master/ros.key"
KEYRING_PATH="/usr/share/keyrings/ros-archive-keyring.gpg"
# --- Script Body ---
main() {
# --- Check for root/sudo privileges ---
if [[ $EUID -ne 0 ]]; then
error "This script must be run with sudo privileges."
info "Please run it as: sudo $0"
exit 1
fi
info "🚀 Starting ROS GPG key fix process..."
# --- Step 1: Remove the old, expired key from apt-key (if it exists) ---
info "Attempting to remove the old GPG key ($OLD_KEY_ID) from apt-key..."
if apt-key del "$OLD_KEY_ID" &>/dev/null; then
success "Old key successfully removed from apt-key."
else
warn "Old key not found in apt-key. This is okay."
fi
# --- Step 2: Install the new GPG key to the recommended location ---
info "Downloading and installing the new ROS GPG key..."
curl -sSL "$NEW_KEY_URL" | gpg --dearmor -o "$KEYRING_PATH"
if [ $? -ne 0 ]; then
error "Failed to download or install the new GPG key. Please check your internet connection."
exit 1
fi
success "New GPG key installed to $KEYRING_PATH"
# --- Step 3: Detect ROS versions ---
ros1_detected=false
ros2_detected=false
info "Detecting installed ROS distributions..."
dpkg -s ros-noetic-desktop-full &>/dev/null && ros1_detected=true
dpkg -s ros-melodic-desktop-full &>/dev/null && ros1_detected=true
dpkg -s ros-humble-desktop &>/dev/null && ros2_detected=true
dpkg -s ros-iron-desktop &>/dev/null && ros2_detected=true
dpkg -s ros-rolling-desktop &>/dev/null && ros2_detected=true
[[ "$ros1_detected" = true ]] && info "Found ROS 1 installation."
[[ "$ros2_detected" = true ]] && info "Found ROS 2 installation."
# --- Step 4: Determine which version to fix based on user input if needed ---
fix_target="none"
if [[ "$ros1_detected" = true && "$ros2_detected" = true ]]; then
warn "Both ROS 1 and ROS 2 installations were detected."
PS3="Please select which repository to fix: "
select choice in "ROS 1" "ROS 2" "Both"; do
case $choice in
"ROS 1") fix_target="ros1"; break;;
"ROS 2") fix_target="ros2"; break;;
"Both") fix_target="both"; break;;
*) echo "Invalid option. Please try again.";;
esac
done
elif [[ "$ros1_detected" = true ]]; then
fix_target="ros1"
elif [[ "$ros2_detected" = true ]]; then
fix_target="ros2"
else
warn "No standard ROS installation detected. Will attempt to set up both ROS 1 and ROS 2 sources."
fix_target="both"
fi
# --- Step 5: Update source lists and install the official management packages ---
info "Updating APT source lists to use the new key..."
if [[ "$fix_target" == "ros1" || "$fix_target" == "both" ]]; then
info "Configuring ROS 1 repository..."
echo "deb [arch=$(dpkg --print-architecture) signed-by=$KEYRING_PATH] http://packages.ros.org/ros/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros1-latest.list > /dev/null
info "Updating package list for ROS 1..."
apt-get update
info "Installing official ROS 1 key management package 'ros-apt-source'..."
apt-get install -y ros-apt-source
fi
if [[ "$fix_target" == "ros2" || "$fix_target" == "both" ]]; then
info "Configuring ROS 2 repository..."
echo "deb [arch=$(dpkg --print-architecture) signed-by=$KEYRING_PATH] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2-latest.list > /dev/null
info "Updating package list for ROS 2..."
apt-get update
info "Installing official ROS 2 key management package 'ros2-apt-source'..."
apt-get install -y ros2-apt-source
fi
# --- Step 6: Final verification ---
info "Running final 'apt-get update' to verify the fix..."
if apt-get update; then
success "✅ All done! The ROS GPG key issue has been resolved."
info "You can now install and update ROS packages normally."
else
error "The final 'apt-get update' failed. The issue might not be fully resolved."
error "Please review the output above for any errors."
fi
}
main "$@"
以上script是由Gemini輔助生成,如果有遇到任何問題,歡迎提出來唷!
ROS signing key migration guide
Reddit - Ros install GPG key error
您好,我使用 ROS1,使用 sudo apt install ros-apt-source 指令安裝。
但出現這樣的錯誤,可能是甚麼問題呢?
錯誤訊息: Unable to locate package ros-apt-source