WinRM 远程操作 Windows 服务器(通用版)
从本机通过 WinRM(HTTP 5985 + NTLM) 远程驱动任意内网 Windows 服务器:
跑 PowerShell、传文件、查状态。服务器信息不写死在代码里,由使用者配置。
第 0 步:检查配置(每次会话首次使用时做)
检查本技能 scripts/config.json 是否存在:
- 不存在 → 向用户要三项信息:服务器 IP、用户名、密码(可用 AskUserQuestion),
然后参照scripts/config.example.json写入scripts/config.json。 - 已存在但用户提到的是另一台服务器 → 临时用环境变量覆盖,不改配置:
set WINRM_HOST=x.x.x.x&& set WINRM_USER=xxx&& set WINRM_PASSWORD=xxx&& python scripts/run_remote.py ...
目标服务器前置条件(只需做一次,由服务器管理员在目标机本地执行):
管理员权限运行 winrm quickconfig,防火墙放行 5985/TCP 入站。
依赖:本机 pip install pywinrm(脚本缺失时会自动提示)。
第 1 步:连通性自检
python scripts/check_connection.py
打印远端主机名/系统/时间且 [OK] 即通道可用。失败排查见 reference.md。
第 2 步:远程执行命令
规则:PowerShell 一律先写成 .ps1 文件,再交给执行器——
绝不在 bash 命令行里内联 PowerShell($变量 会被 shell 吃掉)。
python scripts/run_remote.py some_script.ps1 # 执行脚本文件(推荐)
type some_script.ps1 | python scripts/run_remote.py # stdin 喂入
python scripts/run_remote.py -c "hostname" # 仅极简命令可内联
输出末尾 RC=0 表示成功;stderr 里的 CLIXML 进度噪声已自动过滤。
脚本以 UTF-16LE 编码传输,中文路径和中文输出安全。
第 3 步:文件传输
# 上传(本机起临时 HTTP 服务,远端拉取 + MD5 校验,任意大小)
python scripts/push_file.py app.zip 'D:\deploy\app.zip'
# 下载(base64 通道,限小文件,默认 ≤4MB)
python scripts/pull_file.py 'C:\app\config.ini' .\config.ini
多文件上传:先 zip 打包,push 上去后用 run_remote.py 执行
Expand-Archive 解压。大文件下载的做法见 reference.md。
常用操作速查(写成 .ps1 跑)
- 查端口占用:
Get-NetTCPConnection -State Listen -LocalPort 3201 | Select-Object LocalPort,OwningProcess - 按端口杀进程:先上面查到 pid,再
Stop-Process -Id <pid> -Force - 装软件/长任务:注册计划任务后台跑,另起命令轮询(见 reference.md「机制」节)
- 看日志尾部:
Get-Content C:\path\app.log -Tail 50
安全红线
config.json含明文密码:仅限本机内网使用,不要把技能连同 config.json 一起打包外发
(分享技能前先删掉 config.json)。- WinRM 走 HTTP 明文 + NTLM,只在内网用,不要把 5985 暴露公网。
- 杀进程只认端口查到的 pid,不要按进程名批量杀。
机制与坑(必读)
WinRM 会话有 job-object 回收、单条命令 ~11.5KB 上限、PS 5.1 TLS/编码等坑,
全部记录和对策见 reference.md。