基础设施-SSH连接-Windows无sshpass远程操作服务器
问题现象
Windows 11 环境下需要对 CentOS Stream 9 服务器(120.77.218.217)执行远程命令(git pull、systemctl restart 等),但:
- Git Bash 默认没有 sshpass,无法像 Linux 那样 sshpass -p 'password' ssh root@host 'cmd'
- 服务器仅支持密码登录,未配置 SSH Key
- taskkill / netstat 等 Windows 命令在 Git Bash 下表现不一致
核心问题
Windows Git Bash 与 Linux 的运维工具链存在差异,主要表现在:
1. sshpass 缺失:Git Bash 未预装 sshpass,通过 pacman -S sshpass 安装不稳定
2. SSH 客户端行为差异:Git Bash 的 OpenSSH 不支持 ControlMaster(Unix socket 在 Windows 上不兼容)
3. 端口管理 CLI 差异:Git Bash 中 taskkill //F //IM node.exe 无法正确终止 Windows 进程,需用 PowerShell 的 Stop-Process
解决方案
整个演进分为两个阶段,第二阶段是最终推荐方案。
第一阶段:paramiko 密码认证(过渡方案)
Python 的 paramiko 是 Windows Git Bash 下唯一稳定可用的程序化 SSH 方式,不依赖外部二进制文件。
适用场景:临时排查、紧急操作、尚未配置密钥时。
操作方式:在本地执行 Python 单行脚本
venv/Scripts/python.exe -c "
import paramiko
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect('120.77.218.217', username='root', password='你的密码', timeout=15)
def run(cmd):
stdin, stdout, stderr = c.exec_command(cmd)
out = stdout.read().decode()
err = stderr.read().decode()
if err:
print('ERR:', err.strip())
return out.strip()
# --- 在此处执行远程命令 ---
print(run('cd /www/news && git log --oneline -1'))
print(run('systemctl status news-backend --no-pager -l | head -10'))
c.close()
"
缺陷:
- 密码明文出现在命令中(进程列表、历史记录可见)
- 需要额外依赖 paramiko 库
- 每次都要写完整连接代码,不简洁
- 不适合频繁、多步操作
第二阶段:SSH 密钥 + Config 别名(最终方案)
配置 SSH Key 免密登录 + ~/.ssh/config 别名后,ssh news 一条命令即可远程执行任意操作。
2.1 生成密钥对
在 Windows PowerShell 或 Git Bash 中执行:
ssh-keygen -t ed25519 -C "news-server" -f ~/.ssh/id_ed25519_news
一路回车,不设 passphrase(设了每次都要输,影响自动化)。
- 私钥:
~/.ssh/id_ed25519_news - 公钥:
~/.ssh/id_ed25519_news.pub
2.2 上传公钥到服务器
先用 paramiko 把公钥写入服务器 ~/.ssh/authorized_keys:
venv/Scripts/python.exe -c "
import paramiko
pubkey = '你的pub公钥ssh-xxx news-server'
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect('120.77.218.217', username='root', password='你的密码', timeout=15)
def do(cmd):
stdin, stdout, stderr = c.exec_command(cmd)
return stdout.read().decode().strip()
do('mkdir -p ~/.ssh && chmod 700 ~/.ssh')
do('printf \"%s\\n\" \"{}\" >> ~/.ssh/authorized_keys'.format(pubkey))
do('chmod 600 ~/.ssh/authorized_keys')
do('sort -u ~/.ssh/authorized_keys -o ~/.ssh/authorized_keys')
print('Done - 公钥已写入,条目数:', do('wc -l < ~/.ssh/authorized_keys'))
c.close()
"
注意:
printf比echo更安全,不会因特殊字符导致转义问题;sort -u可避免重复追加公钥。
2.3 创建 SSH Config 文件
在 C:\Users\Administrator\.ssh\config(无后缀名)写入:
Host news
HostName 120.77.218.217
User root
IdentityFile ~/.ssh/id_ed25519_news
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
避坑:不要添加
ControlMaster/ControlPath。Windows Git Bash 的 OpenSSH 不完全支持 Unix socket,会导致mux_client_request_session: read from master failed错误。
2.4 测试连接
ssh news "echo '连接成功' && hostname && uptime"
预期输出无需密码直接返回服务器信息。
2.5 日常使用
从此服务器操作简化为一行命令:
# 查看状态
ssh news "systemctl status news-backend --no-pager | head -5"
# 部署代码
ssh news "cd /www/news && git pull origin main"
# 重启服务
ssh news "systemctl restart news-backend"
# 多条命令组合
ssh news "cd /www/news && git pull origin main && systemctl restart news-backend"
下次防错措施
- 新机器配置清单:换电脑或重装系统后,按 2.1 → 2.2 → 2.3 流程重新配置,全程不超过 3 分钟。
- 密钥备份:私钥
~/.ssh/id_ed25519_news妥善备份,不要提交到 Git 仓库。 - Config 文件模板:
~/.ssh/config内容已记录在上述文档,可直接复制使用。 - Windows 特有问题速查:
ControlMaster报错 → 从 config 中删除该配置- 端口进程管理 → 优先用 PowerShell
Get-NetTCPConnection | Stop-Process,而非 Git Bash 的taskkill - SSH 连接卡住 →
rm -f ~/.ssh/ssh_mux_*清理残留 socket(如曾尝试过 multiplexing) - CODEBUDDY.md 索引:项目
docs/config/server-deploy.md中维护了最新的 SSH 连接方式和部署流程,作为权威参考。