Jenkins服務(wù)器更新密鑰后任務(wù)構(gòu)建不了的排查實(shí)錄與解決方案
前言:在一次生產(chǎn)環(huán)境的 SSH 密鑰輪換中,我遇到了一個極其令人困惑的問題:在 Jenkins 服務(wù)器上手動執(zhí)行 ssh -i 命令測試新密鑰到目標(biāo)服務(wù)器,直接報(bào) Permission denied;將同樣的命令放入 Jenkins 任務(wù)腳本中,同樣失敗。 在排除了文件權(quán)限、換行符、known_hosts 等所有常見原因后,最終發(fā)現(xiàn)是 ssh-agent 緩存的老密鑰在“作祟”,而解決方法是在 ~/.ssh/config 中為堡壘機(jī)單獨(dú)配置 IdentitiesOnly yes。
本文記錄了完整的排查過程,希望能幫助遇到類似“幽靈”故障的運(yùn)維人員快速定位問題。
一、現(xiàn)象:手動測試失敗,Jenkins 任務(wù)也失敗
在 Jenkins 服務(wù)器上執(zhí)行以下命令手動測試新密鑰:
ssh -i ~/.ssh/id_ed25519_new -J user@bastion_ip:22222 target_ip "echo '連通'"
結(jié)果: 報(bào) Permission denied。
再將同樣的命令放入 Jenkins 任務(wù)腳本中:
scp -i ~/.ssh/id_ed25519_new -o 'ProxyJump user@bastion_ip:22222' ...
結(jié)果: Jenkins 控制臺同樣輸出 Permission denied。
手動與腳本表現(xiàn)一致——說明問題不在 Jenkins 任務(wù)執(zhí)行環(huán)境,而在基礎(chǔ)的 SSH 連接鏈路本身。
二、排查:繞過的彎路
- 檢查服務(wù)器端
authorized_keys:確認(rèn)新公鑰已正確添加,權(quán)限為600,文件末尾有換行符。 - 重置
known_hosts:ssh-keygen -R bastion_ip,無效。 - 在腳本中增加參數(shù):
-o StrictHostKeyChecking=no,依然報(bào)Permission denied。 - 清空
ssh-agent緩存:ssh-add -D,依然無效。
這些操作均無法解決問題,說明問題不在表面,而在 SSH 認(rèn)證的深層機(jī)制。
三、真相:SSH 的密鑰優(yōu)先級順序
經(jīng)過反復(fù)驗(yàn)證,發(fā)現(xiàn) SSH 在認(rèn)證時的密鑰優(yōu)先級是:
- 最高優(yōu)先級:
ssh-agent中緩存的密鑰。 - 中間優(yōu)先級:命令行
-i參數(shù)指定的密鑰。 - 最低優(yōu)先級:
~/.ssh/id_rsa等默認(rèn)密鑰。
在 Jenkins 節(jié)點(diǎn)上,后臺進(jìn)程悄悄地啟動了 ssh-agent,并將舊的 id_rsa 密鑰加載了進(jìn)去。
當(dāng)我們在手動測試或 Jenkins 腳本中執(zhí)行 ssh -i ~/.ssh/id_ed25519_new ... 時,SSH 客戶端會優(yōu)先問 ssh-agent:“你有能用的鑰匙嗎?”
ssh-agent 回答:“有,我這里有 id_rsa。”
于是 SSH 嘗試用 舊密鑰 id_rsa 去連接堡壘機(jī)。此時,堡壘機(jī)上的老公鑰已被刪除,認(rèn)證失敗,連接被服務(wù)端直接切斷。切斷后,SSH 根本沒機(jī)會再去嘗試你 -i 指定的新密鑰。
這就是為什么手動測試和 Jenkins 任務(wù)都失敗的根本原因。
四、終極解決方案:配置~/.ssh/config
在 Jenkins 節(jié)點(diǎn)上,修改 ~/.ssh/config 文件,為堡壘機(jī)添加強(qiáng)制隔離配置:
Host bastion_ip
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519_new
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
核心參數(shù)解析:
bastion_ip:指構(gòu)建任務(wù)時的目標(biāo)服務(wù)器的ip,這里可以配制多個,用空格隔開,比如10.0.0.1 10.0.0.2 10.0.0.3。IdentitiesOnly yes:強(qiáng)制 SSH 客戶端只使用IdentityFile指定的密鑰,完全忽略ssh-agent中緩存的所有密鑰。這是解決“-i參數(shù)失效”的關(guān)鍵。IdentityFile:指定要使用的新密鑰文件。StrictHostKeyChecking no&UserKnownHostsFile /dev/null:跳過主機(jī)指紋校驗(yàn),避免 SSH 在自動化環(huán)境中卡住。
五、驗(yàn)證與成果
添加配置后,再次執(zhí)行手動測試命令(不再需要 -i 參數(shù)):
ssh -J user@bastion_ip:22222 target_ip "echo '連通'"
結(jié)果: 成功輸出 連通。
直接重跑 Jenkins 任務(wù)——構(gòu)建成功,密鑰輪換完成。
六、經(jīng)驗(yàn)總結(jié):下次輪換密鑰該怎么做?
- 不要依賴腳本里的
-i參數(shù):在 Jenkins 這種有ssh-agent的環(huán)境里,單獨(dú)指定-i往往不可靠,因?yàn)?ssh-agent的優(yōu)先級更高。 - 善用
~/.ssh/config:為跳板機(jī)或目標(biāo)服務(wù)器單獨(dú)配置IdentitiesOnly yes和IdentityFile,可以做到“一勞永逸”。 - 清理服務(wù)器端的舊公鑰:確保新公鑰是唯一可用的。
- 后續(xù)輪換:下次更新密鑰時,你只需要修改
~/.ssh/config里的IdentityFile路徑,所有 Jenkins 任務(wù)會自動切換到新密鑰,無需修改任何 Jenkins 腳本。
希望這篇博客能幫你快速定位這類 Jenkins 密鑰更新后的連接失敗問題。如果你也遇到過類似的“幽靈”報(bào)錯,不妨試試在 ~/.ssh/config 里加上 IdentitiesOnly yes,或許能節(jié)省數(shù)小時的不必要排查。
以上就是Jenkins服務(wù)器更新密鑰后任務(wù)構(gòu)建不了的排查實(shí)錄與解決方案的詳細(xì)內(nèi)容,更多關(guān)于Jenkins更新密鑰后任務(wù)無法構(gòu)建解決的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
idea修改language level版本實(shí)現(xiàn)方式
文章介紹了在不同版本JDK之間的切換時遇到的語言級別版本問題的解決方案,通過修改系統(tǒng)環(huán)境變量、Maven配置和IDEA設(shè)置,可以實(shí)現(xiàn)不同JDK版本的切換,并確保項(xiàng)目順利編譯和運(yùn)行2025-12-12
MyBatis環(huán)境資源配置實(shí)現(xiàn)代碼詳解
這篇文章主要介紹了MyBatis環(huán)境資源配置實(shí)現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08
IDEA的部署設(shè)置改為war exploded運(yùn)行項(xiàng)目出錯問題
在使用IDEA配置warexploded部署時,可能會遇到路徑問題或404錯誤,解決方法是進(jìn)入Deployment設(shè)置,刪除Application content中的/marry_war_exploded,使其為空,然后重新運(yùn)行項(xiàng)目即可,這是一種有效的解決策略,希望能幫助到遇到同樣問題的開發(fā)者2024-10-10
帶你用Java方法輕松實(shí)現(xiàn)樹的同構(gòu)
給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構(gòu)”的。例如圖1給出的兩棵樹就是同構(gòu)的,因?yàn)槲覀儼哑渲幸豢脴涞慕Y(jié)點(diǎn)A、B、G的左右孩子互換后,就得到另外一棵樹2021-06-06
Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動scheduleUpdate定時任務(wù)的流程分析
這篇文章主要介紹了Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動scheduleUpdate定時任務(wù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02
springMVC+velocity實(shí)現(xiàn)仿Datatables局部刷新分頁方法
下面小編就為大家分享一篇springMVC+velocity實(shí)現(xiàn)仿Datatables局部刷新分頁方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02

