使用Packer+Ansible部署Windows虚拟机时,win_shell模块为何忽略默认PowerShell 7仍使用PowerShell 5?
这其实是因为Ansible的win_shell模块和你配置的OpenSSH默认Shell完全是两套独立的执行逻辑,我来给你拆解清楚:
核心原因
win_shell模块的设计目标是直接与Windows系统的执行环境交互,它不会通过OpenSSH的Shell通道来运行命令。模块的默认行为是硬编码调用powershell.exe(也就是PowerShell 5.1),这个默认值和你在OpenSSH里设置的默认Shell没有任何关联——OpenSSH的默认Shell只影响你交互式SSH登录时的环境,而Ansible的win_shell是直接在系统层面启动可执行文件,不走SSH的Shell路由。
这就解释了为什么你手动SSH登录时看到的是PowerShell 7,但win_shell默认返回的是5.1:两者用的是完全不同的启动路径。
解决方案
根据你的需求,有几种不同的方式让win_shell默认使用PowerShell 7:
1. 全局配置Ansible默认Shell
在你的ansible.cfg文件中添加以下配置,让所有win_shell任务默认调用PowerShell 7:
[defaults] win_shell_executable = pwsh
这样所有Playbook里的win_shell任务都会自动使用pwsh.exe,不需要再逐个指定executable参数。
2. Playbook级别设置
如果只想让某个Play里的任务用PowerShell 7,可以在Play的变量中定义:
- name: Configure Windows VM with PowerShell 7 hosts: your_windows_vms vars: ansible_win_shell_executable: pwsh tasks: - name: Verify PowerShell version ansible.windows.win_shell: | Get-Host | Select-Object Version
这个配置会覆盖全局设置,仅对当前Play生效。
3. 单个任务显式指定(你当前的方法)
如果只有个别任务需要PowerShell 7,继续使用你现在的方式即可:
- name: Check powershell version ansible.windows.win_shell: | Get-Host | Select-Object Version args: executable: pwsh
额外选项:用shell模块替代(仅适用于SSH连接)
因为你是通过OpenSSH连接虚拟机,也可以考虑使用Ansible通用的ansible.builtin.shell模块代替win_shell。这个模块会通过SSH的默认Shell执行命令,所以会自动使用你设置的PowerShell 7:
- name: Check powershell version via SSH shell ansible.builtin.shell: | Get-Host | Select-Object Version
这种方式不需要指定任何额外参数,直接复用OpenSSH的默认Shell配置。
总结
win_shell的默认行为和OpenSSH的Shell配置是完全独立的,前者直接调用系统可执行文件,后者只影响交互式登录和通过SSH通道执行的命令。根据你的场景选择上面的任一方案,就能让Ansible默认使用PowerShell 7执行任务了。
内容的提问来源于stack exchange,提问作者Mike A

