jenkins在windows配置sshpass
我的服务器里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!"