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

Ansible远程执行PowerShell脚本时无限期卡住问题求助

问题:Ansible远程执行PowerShell脚本无限期卡住
  • 场景:调用一个创建Hyper-V虚拟机的PowerShell脚本,脚本本地运行正常,但通过Ansible远程执行时卡住
  • 脚本功能:接收3个参数(Hyper-V服务器、存储分区、虚拟机名称),从NAS复制sysprepped VHD文件,完成虚拟机创建与配置
  • Playbook内容:
- hosts: windows_host
  tasks:
   - name: Run remote PowerShell script
     win_shell: powershell.exe -ExecutionPolicy ByPass -File C:/Path/To/Script/Script.ps1 {{ server }} {{ partition }} {{ hostname }}
  • 执行命令:
ansible-playbook /etc/ansible/playbook.yml --extra-var "server=server.mydomain.local partition=E: hostname=devtest" -vvvv
  • 异常现象:WinRM连接建立后无后续输出,卡在EXEC (via pipeline wrapper)阶段;但简单脚本(如创建指定名称文件)可正常执行

环境信息

Ansible版本

ansible [core 2.12.10]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0]
  jinja version = 2.10.1
  libyaml = True

目标主机信息(ansible -i hosts windows_host -m setup输出片段)

  • 操作系统:Microsoft Windows Server 2022 Datacenter
  • 网络地址:192.168.0.100(Hyper-V网络适配器)

Inventory配置

[windows_host]
windows_host.MYDOMAIN.LOCAL

[windows_host:vars]
ansible_user=windows_user@MYDOMAIN.LOCAL
ansible_password= {{ password }}
ansible_connection=winrm
ansible_port=5985
ansible_winrm_transport=kerberos
ansible_winrm_server_cert_validation=ignore
ansible_winrm_read_timeout_sec: 60
ansible_winrm_operation_timeout_sec: 58

涉问题PowerShell脚本内容

$userName="user"
$File="C:\Path\To\User\user.txt"
$hyperv_host=$args[0]
$partition=$args[1]
$host_name=$args[2]
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$userName", (Get-Content $File | ConvertTo-SecureString)

$PSDefaultParameterValues = @{'Invoke-Command:ConfigurationName'='remote_host' }
$nas_location = "Microsoft.PowerShell.Core\FileSystem::\\path\in\NAS\location\VHD\sysprep.vhdx"
Invoke-Command  -Credential $credentials -ScriptBlock {
(New-Item -Verbose "$using:partition\$using:host_name" -type directory)
(Copy-Item -Verbose -Path "$using:nas_location" -Destination "$using:partition\$using:host_name")
(Write-Host "VHD successfully copied from \\NAS\")
(Rename-Item -Verbose -Path "$using:partition\$using:host_name\sysprep.vhdx" -NewName "$using:host_name.vhdx")
(New-VM -Verbose -Name "$using:host_name" -MemoryStartupBytes 16GB -Generation 2  -Path "$using:partition\$using:host_name" -BootDevice VHD -VHDPath "$using:partition\$using:host_name\$using:host_name.vhdx")
(Set-VMProcessor -Verbose "$using:host_name" -Count 4)
    } -ComputerName $hyperv_host

解决建议

1. 调高WinRM超时阈值

当前配置的ansible_winrm_read_timeout_sec=60和ansible_winrm_operation_timeout_sec=58过短,复制大VHD文件、创建虚拟机属于长耗时操作,需大幅调高:

[windows_host:vars]
# 根据VHD大小调整,示例设为5分钟
ansible_winrm_read_timeout_sec=300
ansible_winrm_operation_timeout_sec=290

2. 移除嵌套远程调用

脚本中通过Invoke-Command再次连接Hyper-V服务器,而Ansible已通过WinRM建立远程会话,嵌套调用易引发阻塞。修改脚本直接在Ansible会话上下文执行(需确保Ansible使用的账号拥有Hyper-V管理权限和NAS访问权限):

$hyperv_host=$args[0]
$partition=$args[1]
$host_name=$args[2]

# 直接执行所有操作,去掉Invoke-Command嵌套
New-Item -Verbose "$partition\$host_name" -type directory
Copy-Item -Verbose -Path "\\path\in\NAS\location\VHD\sysprep.vhdx" -Destination "$partition\$host_name"
Write-Host "VHD successfully copied from \\NAS\"
Rename-Item -Verbose -Path "$partition\$host_name\sysprep.vhdx" -NewName "$host_name.vhdx"
New-VM -Verbose -Name "$host_name" -MemoryStartupBytes 16GB -Generation 2  -Path "$partition\$host_name" -BootDevice VHD -VHDPath "$partition\$host_name\$host_name.vhdx"
Set-VMProcessor -Verbose "$host_name" -Count 4

3. 改用Ansible原生模块替代脚本

使用Windows专属模块更可靠,且便于调试:

  • 先安装community.windows集合:ansible-galaxy collection install community.windows
  • 示例Playbook片段:
- hosts: windows_host
  tasks:
    - name: 创建虚拟机目录
      win_file:
        path: "{{ partition }}\\{{ hostname }}"
        state: directory

    - name: 从NAS复制VHD文件
      win_robocopy:
        src: "\\\\path\\in\\NAS\\location\\VHD"
        dest: "{{ partition }}\\{{ hostname }}"
        files: sysprep.vhdx
        recurse: no

    - name: 重命名VHD文件
      win_command: Rename-Item "{{ partition }}\\{{ hostname }}\\sysprep.vhdx" "{{ hostname }}.vhdx"

    - name: 创建Hyper-V虚拟机
      community.windows.win_hyperv_vm:
        name: "{{ hostname }}"
        generation: 2
        memory_startup: 16GB
        vhd_path: "{{ partition }}\\{{ hostname }}\\{{ hostname }}.vhdx"
        path: "{{ partition }}\\{{ hostname }}"
        state: present

    - name: 设置虚拟机CPU核心数
      community.windows.win_hyperv_vm:
        name: "{{ hostname }}"
        processors: 4
        state: present

4. 添加脚本日志排查卡点

在脚本中添加文件日志输出(WinRM无法捕获Write-Host内容),确认卡住的具体步骤:

$logPath = "C:\temp\vm_create.log"
"[$(Get-Date)] 脚本启动,参数:$args" | Out-File -FilePath $logPath -Append

"[$(Get-Date)] 创建目录:$partition\$host_name" | Out-File -FilePath $logPath -Append
New-Item -Verbose "$partition\$host_name" -type directory 4>&1 | Out-File -FilePath $logPath -Append

"[$(Get-Date)] 复制VHD文件" | Out-File -FilePath $logPath -Append
Copy-Item -Verbose -Path "\\path\in\NAS\location\VHD\sysprep.vhdx" -Destination "$partition\$host_name" 4>&1 | Out-File -FilePath $logPath -Append

# 后续步骤同理添加日志

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:45:46