iT邦幫忙

2

apt update噴錯誤?ROS GPG 金鑰過期解決方法 (EXPKEYSIG F42ED6FBAB17C654)

  • 分享至 

  • xImage
  •  

前情提要

不曉得各位有在使用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 系統的解決步驟:

  1. 移除舊的、已過期的金鑰
    首先,我們需要將系統中舊的 ROS 金鑰刪除,避免產生衝突。請打開你的終端機,執行以下指令:

    sudo apt-key del "F42ED6FBAB17C654"
    

    如果系統回報找不到該金鑰,也沒關係,代表你的系統中本來就沒有這把舊鑰匙,可以直接進行下一步。

  2. 安裝新的金鑰管理包
    接下來,根據你使用的 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/)。

  3. 更新並驗證
    完成上一步後,你的系統就已經配置好了新的金鑰與來源。現在,再次執行更新指令來驗證成果:

    sudo apt update
    

    如果終端機順利地完成更新,沒有再出現 EXPKEYSIG F42ED6FBAB17C654 的錯誤訊息,那麼恭喜你,問題已經完美解決!你現在可以正常地安裝或更新任何 ROS 相關的軟體包了。

懶人包

為了讓大家更方便,這裡提供一個簡單的 Bash Script,它會自動偵測你的環境並執行上述所有修復步驟。

使用方法:

  1. 將下面的程式碼儲存為一個檔案,例如 fix_ros_key.sh
  2. 給予執行的權限:chmod +x fix_ros_key.sh
  3. 執行: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


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jingccc
iT邦新手 5 級 ‧ 2025-08-27 15:10:51

您好,我使用 ROS1,使用 sudo apt install ros-apt-source 指令安裝。
但出現這樣的錯誤,可能是甚麼問題呢?
錯誤訊息: Unable to locate package ros-apt-source

我要留言

立即登入留言