使用 ansible 从 linux 主机在 Windows 目标主机中执行 cmd 命令
Execute cmd commands in Windows target host from linux host using ansible
我正在尝试联系我在 Azure 门户中创建的 Windows 目标 VM。但即使在端口 5986 上启用 winrm 之后,我也无法使用 ansible 主机访问该目标虚拟机。
VM 是使用以下剧本文件创建的 create_win.yml:
- hosts: localhost
tasks:
- name: Prepare random postfix
set_fact:
rpfx: "{{ 100000 | random }}"
run_once: yes
- name: provision new azure host
hosts: localhost
connection: local
vars:
resource_group: myTestRG
vm_name: wintestvm{{ rpfx }}
vm_user: azureuser
vm_password: MyPassword123!!!
location: eastus
# Below is UTF-16 Base64 encoding for:
# Invoke-Expression -Command ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1')); Enable-WSManCredSSP -Role Server -Force
winrm_enable_script: SQBuAHYAbwBrAGUALQBFAHgAcAByAGUAcwBzAGkAbwBuACAALQBDAG8AbQBtAGEAbgBkACAAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQAKQAuAEQAbwB3AG4AbABvAGEAZABTAHQAcgBpAG4AZwAoACcAaAB0AHQAcABzADoALwAvAHIAYQB3AC4AZwBpAHQAaAB1AGIAdQBzAGUAcgBjAG8AbgB0AGUAbgB0AC4AYwBvAG0ALwBhAG4AcwBpAGIAbABlAC8AYQBuAHMAaQBiAGwAZQAvAGQAZQB2AGUAbAAvAGUAeABhAG0AcABsAGUAcwAvAHMAYwByAGkAcAB0AHMALwBDAG8AbgBmAGkAZwB1AHIAZQBSAGUAbQBvAHQAaQBuAGcARgBvAHIAQQBuAHMAaQBiAGwAZQAuAHAAcwAxACcAKQApADsAIABFAG4AYQBiAGwAZQAtAFcAUwBNAGEAbgBDAHIAZQBkAFMAUwBQACAALQBSAG8AbABlACAAUwBlAHIAdgBlAHIAIAAtAEYAbwByAGMAZQA=
tasks:
- name: create Azure virtual network in resource group
azure_rm_virtualnetwork:
name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
address_prefixes_cidr:
- 10.1.0.0/16
state: present
- name: create Azure subnet in virtualnetwork
azure_rm_subnet:
name: '{{ vm_name }}'
state: present
virtual_network_name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
address_prefix_cidr: 10.1.0.0/24
- name: create Azure storage account
azure_rm_storageaccount:
name: '{{ vm_name }}'
resource_group: "{{ resource_group }}"
account_type: Standard_LRS
- name: provision new Azure virtual host
azure_rm_virtualmachine:
admin_username: '{{ vm_user }}'
admin_password: "{{ vm_password }}"
os_type: Windows
image:
offer: WindowsServer
publisher: MicrosoftWindowsServer
sku: 2016-Datacenter
version: latest
name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
state: present
vm_size: Standard_D1
storage_account_name: "{{ vm_name }}"
virtual_network_name: "{{ vm_name }}"
subnet_name: "{{ vm_name }}"
- name: create Azure vm extension to enable HTTPS WinRM listener
azure_rm_virtualmachine_extension:
name: winrm-extension
resource_group: "{{ resource_group }}"
virtual_machine_name: "{{ vm_name }}"
publisher: Microsoft.Compute
virtual_machine_extension_type: CustomScriptExtension
type_handler_version: 1.9
settings: '{"commandToExecute": "powershell.exe -ExecutionPolicy ByPass -EncodedCommand {{winrm_enable_script}}"}'
auto_upgrade_minor_version: true
- name: wait for the WinRM port to come online
wait_for:
port: 5986
host: '{{azure_vm.properties.networkProfile.networkInterfaces[0].properties.ipConfigurations[0].properties.publicIPAddress.properties.ipAddress}}'
timeout: 600
我创建了 inventory.txt 文件,内容如下:
target1 ansible_host=<my-target-ip-pasted-here> ansible_user=azureuser ansible_password=MyPassword123!!! ansible_connection=winrm ansible_winrm_server_cert_validation=ignore
运行之后:
ansible target1 -m ping -i inventory.txt
我的输出低于:
[WARNING]: No python interpreters found for host target1 (tried ['/usr/bin/python', 'python3.7', 'python3.6', 'python3.5', 'python2.7', 'python2.6', '/usr/libexec/platform-python', '/usr/bin/python3', 'python'])
target1 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Exception calling \"Create\" with \"1\" argument(s): \"At line:4 char:21\r\n+ def _ansiballz_main():\r\n+ ~\r\nAn expression was expected after '('.\r\nAt line:13 char:27\r\n+ except (AttributeError, OSError):\r\n+ ~\r\nMissing argument in parameter list.\r\nAt line:15 char:7\r\n+ if scriptdir is not None:\r\n+ ~\r\nMissing '(' after 'if' in if statement.\r\nAt line:22 char:7\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nMissing '(' after 'if' in if statement.\r\nAt line:22 char:30\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nMissing expression after ','.\r\nAt line:22 char:25\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nThe '<' operator is reserved for future use.\r\nAt line:24 char:32\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nMissing expression after ','.\r\nAt line:24 char:33\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~~~~~~~~~~~~~\r\nUnexpected token 'imp.PY_SOURCE' in expression or statement.\r\nAt line:24 char:32\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nMissing closing ')' in expression.\r\nAt line:24 char:46\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nUnexpected token ')' in expression or statement.\r\nNot all parse errors were reported. Correct the reported errors and try again.\"\r\nAt line:6 char:1\r\n+ $exec_wrapper = [ScriptBlock]::Create($split_parts[0])\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : NotSpecified: (:) [], MethodInvocationException\r\n + FullyQualifiedErrorId : ParseException\r\n \r\nThe expression after '&' in a pipeline element produced an object that was not valid. It must result in a command \r\nname, a script block, or a CommandInfo object.\r\nAt line:7 char:2\r\n+ &$exec_wrapper\r\n+ ~~~~~~~~~~~~~\r\n + CategoryInfo : InvalidOperation: (:) [], RuntimeException\r\n + FullyQualifiedErrorId : BadExpression\r\n ",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
ankur512512@testvmansible-ankur:~$
只是想让你知道,目标机器已经安装了 python,并试图将它复制到 /usr/bin 路径,但我的 ansible 仍然无法与那个 [=33] 通信=] 机。有人可以帮忙吗?
请注意 ping
模块在 Windows 主机上不起作用。对于 Windows,尝试等效的 - win_ping
另外,请注意 WinRM 需要一些 additional preparation steps 才能由 Ansible 管理机器。您是否完成了这些步骤?
对于面临同样问题的其他人。下面是名为 run_windows_cmd.yml 的 ansible-playbook 文件,我用来检查它是否正常工作。然后执行命令:ansible-playbook run_windows_cmd.yml -i inventory.txt
- name: Execute commands on Azure VM
hosts: target1
connection: winrm
tasks:
- name: Run a command under cmd
win_shell: mkdir test
之后我可以看到在 azureuser 的主目录中创建了一个测试目录。
我正在尝试联系我在 Azure 门户中创建的 Windows 目标 VM。但即使在端口 5986 上启用 winrm 之后,我也无法使用 ansible 主机访问该目标虚拟机。
VM 是使用以下剧本文件创建的 create_win.yml:
- hosts: localhost
tasks:
- name: Prepare random postfix
set_fact:
rpfx: "{{ 100000 | random }}"
run_once: yes
- name: provision new azure host
hosts: localhost
connection: local
vars:
resource_group: myTestRG
vm_name: wintestvm{{ rpfx }}
vm_user: azureuser
vm_password: MyPassword123!!!
location: eastus
# Below is UTF-16 Base64 encoding for:
# Invoke-Expression -Command ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1')); Enable-WSManCredSSP -Role Server -Force
winrm_enable_script: SQBuAHYAbwBrAGUALQBFAHgAcAByAGUAcwBzAGkAbwBuACAALQBDAG8AbQBtAGEAbgBkACAAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQAKQAuAEQAbwB3AG4AbABvAGEAZABTAHQAcgBpAG4AZwAoACcAaAB0AHQAcABzADoALwAvAHIAYQB3AC4AZwBpAHQAaAB1AGIAdQBzAGUAcgBjAG8AbgB0AGUAbgB0AC4AYwBvAG0ALwBhAG4AcwBpAGIAbABlAC8AYQBuAHMAaQBiAGwAZQAvAGQAZQB2AGUAbAAvAGUAeABhAG0AcABsAGUAcwAvAHMAYwByAGkAcAB0AHMALwBDAG8AbgBmAGkAZwB1AHIAZQBSAGUAbQBvAHQAaQBuAGcARgBvAHIAQQBuAHMAaQBiAGwAZQAuAHAAcwAxACcAKQApADsAIABFAG4AYQBiAGwAZQAtAFcAUwBNAGEAbgBDAHIAZQBkAFMAUwBQACAALQBSAG8AbABlACAAUwBlAHIAdgBlAHIAIAAtAEYAbwByAGMAZQA=
tasks:
- name: create Azure virtual network in resource group
azure_rm_virtualnetwork:
name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
address_prefixes_cidr:
- 10.1.0.0/16
state: present
- name: create Azure subnet in virtualnetwork
azure_rm_subnet:
name: '{{ vm_name }}'
state: present
virtual_network_name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
address_prefix_cidr: 10.1.0.0/24
- name: create Azure storage account
azure_rm_storageaccount:
name: '{{ vm_name }}'
resource_group: "{{ resource_group }}"
account_type: Standard_LRS
- name: provision new Azure virtual host
azure_rm_virtualmachine:
admin_username: '{{ vm_user }}'
admin_password: "{{ vm_password }}"
os_type: Windows
image:
offer: WindowsServer
publisher: MicrosoftWindowsServer
sku: 2016-Datacenter
version: latest
name: "{{ vm_name }}"
resource_group: "{{ resource_group }}"
state: present
vm_size: Standard_D1
storage_account_name: "{{ vm_name }}"
virtual_network_name: "{{ vm_name }}"
subnet_name: "{{ vm_name }}"
- name: create Azure vm extension to enable HTTPS WinRM listener
azure_rm_virtualmachine_extension:
name: winrm-extension
resource_group: "{{ resource_group }}"
virtual_machine_name: "{{ vm_name }}"
publisher: Microsoft.Compute
virtual_machine_extension_type: CustomScriptExtension
type_handler_version: 1.9
settings: '{"commandToExecute": "powershell.exe -ExecutionPolicy ByPass -EncodedCommand {{winrm_enable_script}}"}'
auto_upgrade_minor_version: true
- name: wait for the WinRM port to come online
wait_for:
port: 5986
host: '{{azure_vm.properties.networkProfile.networkInterfaces[0].properties.ipConfigurations[0].properties.publicIPAddress.properties.ipAddress}}'
timeout: 600
我创建了 inventory.txt 文件,内容如下:
target1 ansible_host=<my-target-ip-pasted-here> ansible_user=azureuser ansible_password=MyPassword123!!! ansible_connection=winrm ansible_winrm_server_cert_validation=ignore
运行之后:
ansible target1 -m ping -i inventory.txt
我的输出低于:
[WARNING]: No python interpreters found for host target1 (tried ['/usr/bin/python', 'python3.7', 'python3.6', 'python3.5', 'python2.7', 'python2.6', '/usr/libexec/platform-python', '/usr/bin/python3', 'python'])
target1 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Exception calling \"Create\" with \"1\" argument(s): \"At line:4 char:21\r\n+ def _ansiballz_main():\r\n+ ~\r\nAn expression was expected after '('.\r\nAt line:13 char:27\r\n+ except (AttributeError, OSError):\r\n+ ~\r\nMissing argument in parameter list.\r\nAt line:15 char:7\r\n+ if scriptdir is not None:\r\n+ ~\r\nMissing '(' after 'if' in if statement.\r\nAt line:22 char:7\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nMissing '(' after 'if' in if statement.\r\nAt line:22 char:30\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nMissing expression after ','.\r\nAt line:22 char:25\r\n+ if sys.version_info < (3,):\r\n+ ~\r\nThe '<' operator is reserved for future use.\r\nAt line:24 char:32\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nMissing expression after ','.\r\nAt line:24 char:33\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~~~~~~~~~~~~~\r\nUnexpected token 'imp.PY_SOURCE' in expression or statement.\r\nAt line:24 char:32\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nMissing closing ')' in expression.\r\nAt line:24 char:46\r\n+ MOD_DESC = ('.py', 'U', imp.PY_SOURCE)\r\n+ ~\r\nUnexpected token ')' in expression or statement.\r\nNot all parse errors were reported. Correct the reported errors and try again.\"\r\nAt line:6 char:1\r\n+ $exec_wrapper = [ScriptBlock]::Create($split_parts[0])\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : NotSpecified: (:) [], MethodInvocationException\r\n + FullyQualifiedErrorId : ParseException\r\n \r\nThe expression after '&' in a pipeline element produced an object that was not valid. It must result in a command \r\nname, a script block, or a CommandInfo object.\r\nAt line:7 char:2\r\n+ &$exec_wrapper\r\n+ ~~~~~~~~~~~~~\r\n + CategoryInfo : InvalidOperation: (:) [], RuntimeException\r\n + FullyQualifiedErrorId : BadExpression\r\n ",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
ankur512512@testvmansible-ankur:~$
只是想让你知道,目标机器已经安装了 python,并试图将它复制到 /usr/bin 路径,但我的 ansible 仍然无法与那个 [=33] 通信=] 机。有人可以帮忙吗?
请注意 ping
模块在 Windows 主机上不起作用。对于 Windows,尝试等效的 - win_ping
另外,请注意 WinRM 需要一些 additional preparation steps 才能由 Ansible 管理机器。您是否完成了这些步骤?
对于面临同样问题的其他人。下面是名为 run_windows_cmd.yml 的 ansible-playbook 文件,我用来检查它是否正常工作。然后执行命令:ansible-playbook run_windows_cmd.yml -i inventory.txt
- name: Execute commands on Azure VM
hosts: target1
connection: winrm
tasks:
- name: Run a command under cmd
win_shell: mkdir test
之后我可以看到在 azureuser 的主目录中创建了一个测试目录。