使用vmware_tools连接时Ansible在Windows服务器执行失败问题
问题场景
我在给VMware vCenter中的Windows虚拟机配置WinRM时,采用Ansible的vmware_tools连接方式,执行win_file创建目录和win_copy复制文件的playbook时,多数服务器都失败了,仅少数能正常运行。
我的playbook代码如下:
- name: "win_winrm | main.yml | Create temporary dir 'tmp_ansible' on C:Sistemas unit" win_file: path: C:\Sistemas\tmp_ansible state: directory - name: "win_winrm | main.yml | Copy ConfigureRemotingForAnsible.ps1 script into Windows machine" win_copy: src: files/ConfigureRemotingForAnsible.ps1 dest: C:\Sistemas\tmp_ansible\ConfigureRemotingForAnsible.ps1
执行win_file时出现无标准输出的失败,核心报错为找不到Ansible临时文件路径:
TASK [win_winrm : win_winrm | main.yml | Create temporary dir 'tmp_ansible' on C:Sistemas unit] *** [WARNING]: Error deleting remote temporary files (rc: 1, stderr: #< CLIXML <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>Sy stem.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><S S="Error">Remove-Item : Cannot find path 'C:\Users\TEMP\AppData\Local\Temp\ansible- tmp-1674134258.9689112-102-136885899008081' _x000D__x000A_</S><S S="Error">because it does not exist._x000D__x000A_</S><S S="Error">At line:2 char:1_x000D__x000A_</S><S S="Error">+ Remove-Item 'C:\Users\TEMP\AppData\Local\Temp\ansible-tmp-1674134258. ..._x000D__x000A_</S><S S="Error">+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~… An exception occurred during task execution. To see the full traceback, use -vvv. The error was: } fatal: [wsy01iedi.rmasede.grma.net]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
已确认所用凭据具备管理员权限,手动登录服务器正常;即便直接复制文件到已有目录,仍会触发相同错误。改用已配置好WinRM的连接方式时,playbook可正常执行;且手动登录一次服务器后,用户配置文件被创建,再用vmware_tools连接也能成功。
问题根源
当Ansible通过vmware_tools连接Windows服务器时,未登录过的用户不会在服务器上自动创建用户配置文件(即C:\Users\<用户名>目录)。而Ansible默认会使用用户配置文件下的临时目录(C:\Users\<用户名>\AppData\Local\Temp)存放模块执行的临时文件,找不到该路径就会导致模块执行失败。
解决方案
针对此问题,有两种可靠的解决方式:
1. 提前创建用户配置文件
在执行win_file/win_copy之前,通过win_shell模块手动创建用户配置文件并在注册表中注册,模拟用户首次登录的过程:
- name: Ensure user profile exists for Ansible user win_shell: | $userName = "{{ ansible_user }}" $ntAccount = New-Object System.Security.Principal.NTAccount($userName) $sid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier]).Value $profilePath = "C:\Users\$userName" # Check if profile directory exists if (-not (Test-Path -Path $profilePath)) { # Create profile directory New-Item -ItemType Directory -Path $profilePath | Out-Null # Register profile in registry $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid" if (-not (Test-Path -Path $regPath)) { New-Item -Path $regPath | Out-Null } Set-ItemProperty -Path $regPath -Name "ProfileImagePath" -Value $profilePath -Type ExpandString } become: yes
执行完该任务后,再运行原有的win_file和win_copy模块即可正常工作。
2. 指定Ansible使用全局临时目录
修改Ansible的临时目录为一个已存在、且所有用户都有权限访问的路径(比如C:\Temp),避开对用户配置文件下临时目录的依赖。
可以在playbook中设置变量:
- name: Set global temp directory for Ansible set_fact: ansible_winrm_temp_dir: "C:\\Temp"
或者在inventory文件中针对目标主机定义该变量:
[windows_vms] wsy01iedi.rmasede.grma.net ansible_winrm_temp_dir=C:\Temp
注意:若C:\Temp目录不存在,需先通过win_file创建(不过此时可能仍会触发原问题,建议优先用第一种方法初始化)。
验证
执行完上述任一解决方案后,重新运行playbook,win_file和win_copy模块即可正常执行,不会再出现找不到临时路径的错误。
内容的提问来源于stack exchange,提问作者Casti

