This gets into why async is not a great option, there’s no real way to determine why the process failed without then checking the status with async_status
or manually checking the async task file to figure out what went wrong. Once you get out of Ansible there is no status checking outside of checking if the process is still running through something like the task manager or procexp.
I’ve stated why that doesn’t work but will try and clarify. Say I have this Ansible task
- ansible.windows.win_powershell:
script: |
Start-Process -FilePath powershell.exe -ArgumentList '-NoExit "Some Id"'
# Time to capture child process details manually
Start-Sleep -Seconds 60
If we were to capture the process tree of this task as it is running you’ll see something like this (the actual tree may slightly differ depending on your connection plugin):
You can see that the spawned PowerShell process in the tree (4136) is a child process of the Ansible task (7356). If we were to look at the process metadata we can see that 4136 is part of a Windows job where one of the job limits is “Kill on Job Close”. Ansible does not set this metadata as it is applied as part of the service which handles the connection and automatically applied to any child process spawned inside that connection to ensure any dangling processes are cleaned up on exit.
The only way to avoid that is to explicitly spawn a process that either breaks away from the job which unfortunately is not exposed at any level in PowerShell or .NET but at the C layer with the CREATE_BREAKAWAY_FROM_JOB flag.
This is essentially what async does and it achieves this with some more complicated code to call CreateProcess
directly with this flag to spawn the process explicitly not in the job.
So taking my example by before and slightly tweaking it to
- name: run process in background
ansible.windows.win_command:
cmd: powershell.exe Start-Sleep -Seconds 120
async: 60
poll: 0
You can see in the process tree that it is no longer tied to the connection (and subsequently the job set to kill any process on close) and has continued to run even though the Ansible task has finished and exited
You can also use async_status with the jid
to get the status of the async task which if it failed will include the error message
ansible win-host -m async_status -a "jid=..."
In my case it returns an error because the task exceeded the 60 second timeout which was expected.
$ ansible SERVER2022 -m async_status -a "jid=j744454629280.9928"
[ERROR]: Task failed: Module failed: failure during async watchdog: timed out waiting for module completion
Origin: <adhoc 'async_status' task>
{'action': {'module': 'async_status', 'args': {'jid': 'j744454629280.9928'}}, 'timeout': 0, 'async_val': 0, 'poll': 15}
SERVER2022 | FAILED! =>
ansible_async_watchdog_pid: 4508
ansible_job_id: j744454629280.9928
changed: false
finished: 1
msg: 'failure during async watchdog: timed out waiting for module completion'
results_file: C:\Users\vagrant-domain\.ansible_async\j744454629280.9928
started: 1
stderr: ''
stderr_lines: <omitted>
stdout: ''
stdout_lines: <omitted>