Start a Long running script in windows and detach

Basically, the need is to start a bat file in particular working directory finish the playbook run without waiting for the script to finish.

Start-Process powershell seems to be the best method for this. If I run the command from the server itself the child processes of the bat file run and all is well.

When I run this from ansible they fail to start. I’ve tried a number of different parameter combinations and haven’t found any success.

- name: execute long running script
  ansible.windows.win_powershell:
    script: |
      Set-Location -Path "{{ long_running_directory }}"
      $process = Start-Process -WorkingDirectory "{{ long_running_directory }}" -FilePath "{{ long_running_script }}" -PassThru
      $process.id
      Get-CimInstance win32_process -Filter "ParentProcessId = $($process.id)" | select Name, ProcessId, CommandLine
  register: long_running_id

The bat file has 3 steps

forfiles /p path /D -15 /M  *.err /C "cmd /c del @path"
forfiles /p pathj /D -15 /M *.txt /C "cmd /c del @path"
perl script.pl parm1 param1

What else can be done to run this?

What do these failures look like? Some detail here might help us help you.

I get the processID of the start-process. There is no error. But the child processes that I would expect do not spawn.

 "long_running_id": {
        "changed": true,
        "debug": [],
        "error": [],
        "failed": false,
        "host_err": "",
        "host_out": "",
        "information": [],
        "output": [
            3868,
            {
                "CommandLine": "\\??\\C:\\Windows\\system32\\conhost.exe 0x4",
                "Name": "conhost.exe",
                "ProcessId": 18992
            }
        ],
        "result": {},
        "verbose": [],
        "warning": []
    }
}

This bit of the response looks like its the id you want

When you launch it, can you check for a matching process id or check event logging for what might be causing it to stop?

When you start a process through a network logon like WinRM/SSH/etc it will be scoped to what Windows calls a “Job”. When the main process that controls this job ends (the Ansible task finished), Windows will stop any remaining processes in that job and thus kills your long running process.

You can use async with poll: 0 to have it run in the background but keep in mind async tasks always have a set timeout. If this is truely something that should be running in the background you really should look at either running it through the task scheduler or a service rather than this adhoc method.

async with poll: 0 can be added to anything? I don’t see that param in the docs

async with poll: 0 can be added to anything? I don’t see that param in the docs

EDIT: Asynchronous actions and polling — Ansible Community Documentation
found these and tried. but it did not leave it running

I looked at service first but it interacts poorly with that. 1. it is a bat file which requires another thing to launch it. 2. used nssm and it throws and error on start, then shows running → paused flipping.

scheduled tasks is not centrally managed and not really how this should be done across large fleet of machines.

Not sure what you mean, there’s modules in Ansible to generate these tasks and do whatever you need.

As for the async/pool your task needs to look like

- name: run process in background
  ansible.windows.win_command:
    cmd: '"{{ batch_script_path }}"'
    chdir: '{{ long_running_directory }}'
  # This will cap the time to just 60 seconds, set it whatever you need
  async: 60
  poll: 0  

The trouble with using async here is

  • You need to specify a timeout, you cannot just have it run indefinitely
  • There is no way to easily retrigger this outside of Ansible
  • There is no way to monitor the process

This is why using a service or scheduled task is more ideal for such scenarios. It is using the official Windows mechanisms to run tasks in the background and gives you the ability to check if it’s still running, restart as needed, and define more complex actions like what to do on a failure, etc. Granted using a service is a bit harder for simple scripts as you need to use something like nssm to wrap it but using a scheduled task is definitely doable here.