Skip to content

async_status


A poll: 0 task starts something and moves on without waiting — which raises an obvious question: how do you ever find out whether it actually finished, and how it went? This chapter covers checking back in, and a genuinely practical pattern built around it.

Capturing The Job ID

A poll: 0 task’s registered result includes a job ID, needed to check on it later:

- name: Start a long job
  ansible.builtin.command: /usr/local/bin/long-running-task.sh
  async: 3600
  poll: 0
  register: job_result

async_status: Checking In Later

- name: Check whether the job has finished
  ansible.builtin.async_status:
    jid: "{{ job_result.ansible_job_id }}"
  register: job_status
  until: job_status.finished
  retries: 30
  delay: 10

until/retries/delay, exactly from the loops section’s retry pattern, applied here to poll a fire-and-forget job’s completion rather than a health-check endpoint — the same underlying idea, a genuinely different use case.

A Realistic Pattern: Multiple Independent Jobs, Checked Together

The real payoff of poll: 0 — starting several genuinely independent long jobs across different hosts, doing other useful work in the meantime, then circling back to confirm they all finished:

- name: Start long jobs on every host
  ansible.builtin.command: /usr/local/bin/long-running-task.sh
  async: 3600
  poll: 0
  register: job_result

- name: Do other unrelated work while those jobs run
  ansible.builtin.debug:
    msg: "Doing other setup work in the meantime"

- name: Wait for every host's job to finish
  ansible.builtin.async_status:
    jid: "{{ job_result.ansible_job_id }}"
  register: job_status
  until: job_status.finished
  retries: 30
  delay: 10

Every host’s long job runs concurrently, in the background, while the play moves on to genuinely unrelated work — only circling back to actually wait once there’s nothing else productive left to do in the meantime.

A Gotcha: Not Every Module Supports async

Some modules — particularly ones involving interactive prompts, or certain connection-plugin-specific behaviors — don’t support async at all, and using it against one either has no effect or produces a confusing error rather than the behavior you’d expect. If a module you’re trying to run asynchronously doesn’t seem to be behaving as documented here, checking that module’s own documentation for async support is the first thing worth confirming, before assuming something else is wrong.

Best Practices

  • Always register a poll: 0 task’s result — without the job ID it captures, there’s no way to check on that job again later at all.
  • Use async_status with until/retries/delay, exactly the loops section’s retry pattern, rather than a single one-shot status check that might catch the job mid-run.
  • Use the fire-and-forget pattern specifically when there’s genuinely other useful work to do while a long job runs — starting several jobs and immediately waiting on all of them one at a time defeats the purpose; the benefit comes from doing something else productive in between.
  • Confirm a module actually supports async before relying on it, rather than assuming universal support.
Last updated on