使用 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 的主目录中创建了一个测试目录。