我的服務器里jenkins是通過docker安裝的,jenkins與項目都部署在同一臺服務器上還好,但是當需要通過jenkins構建,再通過scp遠程推送到別的服務器上,就出問題了,畢竟不是手動執行scp命令,可以手動輸入密碼,所以需要在jenkins所在服務器配置ssh免密登錄
先以root身份進入jenkins容器
docker exec -it --user root jenkins bash
執行cat /etc/os-release,查看jenkins鏡像里實際的操作系統內核
cat /etc/os-release
明白了,我的 Jenkins Docker 容器是 Debian 12 (Bookworm),所以用 apt 安裝工具,不是 ?yum?。
創建腳本setup_ssh_windows.sh
先在宿主機/home/docker/jenkins里創建腳本setup_ssh_windows.sh
#!/bin/bash
set -e# -----------------------------
# 配置參數
# -----------------------------
WINDOWS_USER="Administrator"
WINDOWS_PASS="YourWindowsPassword" # 第一次上傳用
WINDOWS_HOST="192.168.0.11"
SSH_DIR="/var/jenkins_home/.ssh"
SSH_KEY="$SSH_DIR/id_ed25519"
WINDOWS_SSH_DIR="C:\\Users\\Administrator\\.ssh"
AUTHORIZED_KEYS="$WINDOWS_SSH_DIR\\authorized_keys"# -----------------------------
# 安裝必要工具(Debian)
# -----------------------------
if ! command -v ssh >/dev/null 2>&1; thenecho "Installing ssh and sshpass..."apt updateapt install -y openssh-client sshpass
fi# -----------------------------
# 創建本地 SSH 目錄
# -----------------------------
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"# -----------------------------
# 生成 SSH 密鑰(如果不存在)
# -----------------------------
if [ ! -f "$SSH_KEY" ]; thenecho "Generating SSH key..."ssh-keygen -t ed25519 -f "$SSH_KEY" -N "" -qchmod 600 "$SSH_KEY"
elseecho "SSH key already exists."
fi# -----------------------------
# 第一次上傳公鑰到 Windows
# -----------------------------
echo "Uploading public key to Windows host..."# 創建 Windows .ssh 目錄
sshpass -p "$WINDOWS_PASS" ssh -o StrictHostKeyChecking=no $WINDOWS_USER@$WINDOWS_HOST \
"mkdir -p $WINDOWS_SSH_DIR && icacls $WINDOWS_SSH_DIR /grant $WINDOWS_USER:F"# 上傳公鑰
sshpass -p "$WINDOWS_PASS" scp -o StrictHostKeyChecking=no "$SSH_KEY.pub" $WINDOWS_USER@$WINDOWS_HOST:$AUTHORIZED_KEYS# 設置權限
sshpass -p "$WINDOWS_PASS" ssh -o StrictHostKeyChecking=no $WINDOWS_USER@$WINDOWS_HOST \
"icacls $WINDOWS_SSH_DIR /inheritance:r /grant $WINDOWS_USER:F && icacls $AUTHORIZED_KEYS /inheritance:r /grant $WINDOWS_USER:F"echo "? Public key uploaded successfully. You can now use SSH/SCP to Windows without password."
以root用戶執行進入容器
docker exec -it --user root jenkins bash
賦值權限
chmod +x /var/jenkins_home/setup_ssh_windows.sh
執行一次(第一次上傳公鑰):
/var/jenkins_home/setup_ssh_windows.sh
測試免密登錄:
一旦免密成功,后續 Jenkins job 里執行:
ssh -o StrictHostKeyChecking=no Administrator@192.168.0.11 "echo 'SSH login successful!'"
重新構建jenkins里的shell
#!/bin/bash
set -e # 遇到錯誤立即退出echo "Working directory content:"
ls -alhecho "Installing dependencies..."
npm installecho "Building project..."
npm run build:prodecho "Current path:"
pwdecho "Deployment completed successfully."
echo "Uploading dist to remote Windows server..."
scp -o StrictHostKeyChecking=no -r dist/* Administrator@192.168.0.11:/d/nginx-1.22.0/upload
echo "Upload completed!"
重新構建出現問題了
?1?? /var/jenkins_home/.ssh/known_hosts 權限問題?
原因:
- Jenkins 容器里的 ?.??ssh? 目錄或者 ?k??nown_hosts? 文件權限不對
- Jenkins 用戶沒有寫權限
解決辦法:
# 確保 known_hosts 可以寫
mkdir -p /var/jenkins_home/.ssh
chown -R jenkins:jenkins /var/jenkins_home/.ssh
chmod 700 /var/jenkins_home/.ssh
touch /var/jenkins_home/.ssh/known_hosts
chmod 600 /var/jenkins_home/.ssh/known_hosts
2?? SCP 登錄被拒絕(公鑰/密碼失敗)
原因可能是:
- Windows 上 ?authorized_k??eys? 文件或 ?.ssh? 目錄權限不正確
- Windows OpenSSH 對權限很嚴格
- 必須用 ?icacls? 給 Administrator 完全控制
- SCP 連接用的用戶和密鑰不匹配
- Jenkins 容器里默認用 ?jenkins? 用戶
- SCP 連接 Windows 時必須使用你上傳的公鑰對應的私鑰
解決方法:
確保 Windows ?.ssh? 權限正確
在 Windows PowerShell(管理員)執行:
icacls "C:\Users\Administrator\.ssh" /inheritance:r /grant Administrator:F
icacls "C:\Users\Administrator\.ssh\authorized_keys" /inheritance:r /grant Administrator:F
icacls "D:\nginx-1.22.0\upload" /grant Administrator:F
確保 Jenkins 容器使用正確私鑰上傳
cd ?/var/jenkins_home/workspace/asm_front_pro?scp -i /var/jenkins_home/.ssh/id_ed25519 -o StrictHostKeyChecking=no -r dist/* Administrator@192.168.0.11:"D:/nginx-1.22.0/upload"
-i ??/var/jenkins_home/.ssh/id_ed25519? 指定使用免密的私鑰
?-o StrictH??ostKeyChecking=no? 避免第一次連接提示
發現仍然不行,沒戲還是需要密碼,這個就是典型的 Windows OpenSSH 權限問題,經過排查摸索,最終知道問題所在了,因為 Windows 從 2018 年開始,默認禁止 Administrator 用戶用用戶目錄下的 key 文件做公鑰認證(出于安全考慮),必須放到 ?a??dministrators_authorized_keys?。。
1?? 確認 Windows sshd 服務開啟并支持公鑰認證
在 Windows PowerShell(管理員權限)運行:
Get-Service sshd
如果是 Stopped →
Start-Service sshd
然后檢查 ?C??:\ProgramData\ssh\sshd_config? 配置里有:
PubkeyAuthentication yes
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
? 注意:
- 在 Windows 上,管理員賬號的公鑰默認不是用 ?C:\Users\Adminis??trator\.ssh\authorized_keys?,而是必須放到 ?C:\ProgramD??ata\ssh\administrators_authorized_keys?,并且權限非常嚴。
- 這是微軟的安全限制(防止提權)。
2?? 如果是 Administrator 用戶,走系統級 authorized_keys 文件
執行(PowerShell 管理員):
notepad C:\ProgramData\ssh\administrators_authorized_keys
把 ???/var/jenkins_home/.ssh/id_ed25519.pub? 里的內容復制進去,保存。
提示找不到C:\ProgramData\ssh\administrators_authorized_keys
那就說明你 Windows 上的 OpenSSH 還沒創建這個文件,我們可以手動新建并寫入 Jenkins 容器的公鑰。
你按這個流程走就行:
1?? 以管理員身份打開 PowerShell
New-Item -ItemType Directory -Force -Path "C:\ProgramData\ssh"
New-Item -ItemType File -Force -Path "C:\ProgramData\ssh\administrators_authorized_keys"
2?? 把 Jenkins 公鑰寫進去
先在 Jenkins 容器里看公鑰內容:
cat /var/jenkins_home/.ssh/id_ed25519.pub
復制這一整行(?s??sh-ed25519 AAAA...? 開頭的)。
然后在 Windows PowerShell(管理員)執行:
notepad C:\ProgramData\ssh\administrators_authorized_keys
把復制的內容粘貼進去,保存并退出。
3?? 設置嚴格權限(必做,否則直接拒絕)
icacls "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r
icacls "C:\ProgramData\ssh\administrators_authorized_keys" /grant "Administrators:F"
icacls "C:\ProgramData\ssh\administrators_authorized_keys" /grant "SYSTEM:F"
4?? 重啟 sshd 服務
Restart-Service sshd
5?? 回到 Jenkins 容器測試免密
ssh -i /var/jenkins_home/.ssh/id_ed25519 -o StrictHostKeyChecking=no Administrator@192.168.0.11
我踩過這個坑,核心點就是:
- Administrator 不能用 ?~/.ssh/author??ized_keys?
- 必須用 ?C:\ProgramDat??a\ssh\administrators_authorized_keys?
- 必須改權限,不然直接無視你的 key
最終執行shell命令-前端
#!/bin/bash
set -e # 遇到錯誤立即退出# -----------------------------
# Jenkins工作區 & SSH配置
# -----------------------------
WORKSPACE=$(pwd)
REMOTE_USER="Administrator"
REMOTE_HOST="192.168.0.11"
REMOTE_DIR="D:/nginx-1.22.0/upload/asm_front"
SSH_KEY="/var/jenkins_home/.ssh/id_ed25519"# -----------------------------
# 構建前日志
# -----------------------------
echo "[INFO] Working directory content:"
ls -alh "$WORKSPACE"# -----------------------------
# 安裝依賴 & 構建項目
# -----------------------------
echo "[INFO] Installing dependencies..."
npm installecho "[INFO] Building project..."
npm run build:prodecho "[INFO] Current path: $(pwd)"
echo "[SUCCESS] Build completed successfully."# -----------------------------
# 上傳整個 dist 目錄到遠程
# -----------------------------
echo "[INFO] Uploading entire dist directory to remote Windows server..."
scp -i "$SSH_KEY" \-o StrictHostKeyChecking=no \-o UserKnownHostsFile=/dev/null \-r "$WORKSPACE/dist" \$REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR"echo "[SUCCESS] Upload completed successfully!"