You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Debian 11作为Ansible控制器时win_updates模块执行失败问题求助

解决Debian 11控制节点调用Ansible win_updates模块的winrm put_file失败问题

我之前也碰到过Debian控制节点用Ansible管理Windows时的这个坑,你的问题根源很明确——WinRM传输文件时,Windows端输出的Active code page: 1252干扰了JSON解析,导致put_file失败。CentOS上没这个问题,大概率是Debian的Python环境或WinRM客户端行为和CentOS存在差异,下面给你几个亲测有效的解决思路:


1. 强制WinRM使用PowerShell作为默认Shell

默认情况下,Debian上的WinRM连接可能用的是cmd shell,而CentOS大概率默认用PowerShell。cmd执行命令时会主动输出代码页信息,PowerShell则不会。你可以直接在Inventory或者Playbook里指定Shell类型:

方法A:修改Inventory文件

[windows]
ws2016-test01.minimaximal.de ansible_connection=winrm ansible_winrm_shell=powershell

方法B:在Playbook中设置变量

- name: "win_updates"
  hosts: all
  vars:
    ansible_winrm_shell: powershell
  tasks:
    - name: install important updates
      ansible.windows.win_updates:
        category_names:
          - SecurityUpdates
          - CriticalUpdates

这个方法最简单且无副作用,建议优先尝试。


2. 清理Python依赖冲突

从你提供的pip包列表看,同时安装了ansible-base和ansible-core,这两个包存在依赖冲突(Ansible 5+是基于ansible-core的集合包,ansible-base是旧版本的核心)。Debian 11上推荐只保留ansible-core,你可以执行以下命令修复:

# 卸载冲突的旧核心包
pip3 uninstall -y ansible-base

# 重新安装Ansible,强制覆盖依赖
pip3 install ansible==5.2.0 --force-reinstall

清理完依赖后再测试win_updates模块,很多时候这类奇怪的WinRM问题都是依赖冲突导致的。


3. 修改Windows端的代码页配置

如果前两个方法无效,你可以尝试让Windows端不再输出代码页信息:

临时测试(无需重启)

登录Windows Server 2016,打开命令提示符执行:

chcp 65001

切换到UTF-8代码页后,立刻回到Debian控制节点重新运行Playbook测试。

永久生效(需要重启)

  1. 打开Windows「控制面板」→「区域」→「管理」标签页
  2. 点击「更改系统区域设置」
  3. 勾选「Beta版:使用Unicode UTF-8提供全球语言支持」
  4. 重启Windows服务器后再测试

4. 调整WinRM传输配置

你可以尝试修改WinRM的传输模式和编码设置,在Inventory里添加:

ws2016-test01.minimaximal.de ansible_connection=winrm ansible_winrm_transport=basic ansible_winrm_encoding=utf-8

注意:使用basic传输需要先在Windows端开启Basic认证:

Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true

5. 临时修改WinRM插件代码(应急方案)

如果以上方法都救不了你,可以临时修改Debian上的WinRM连接插件,让它忽略开头的代码页文本。找到文件/home/testuser/.local/lib/python3.9/site-packages/ansible/plugins/connection/winrm.py,修改put_file函数里的JSON解析部分:

# 原代码
put_output = json.loads(result.std_out)

# 修改为:过滤掉开头的代码页行
clean_stdout = result.std_out.split('\r\n{"sha1":')[1]
clean_stdout = '{"sha1":' + clean_stdout
put_output = json.loads(clean_stdout)

这个方法是应急用的,后续Ansible更新会覆盖修改,不推荐长期使用,但能帮你先解决当前的自动化需求。

我当时是用思路1解决的,你可以从这个开始试,应该能快速搞定。

内容的提问来源于stack exchange,提问作者minimaximal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 09:32:44