Looking for a Way to Set a Global Task Timeout in Ansible

Hi Everyone,

I’m looking for a module or keyword in Ansible that can enforce a global task timeout.

Purpose:
We want to ensure that if a running Ansible task takes too long or hangs, it gets automatically timed out, allowing the rest of the tasks in the playbook to continue.

Given that our Ansible framework is quite large, it’s not feasible to go and add --timeout=600 or similar timeouts to each task manually.

Is there a recommended way to implement this kind of global timeout behavior across all tasks?

Thanks in advance for your suggestions!

Hi!

You can use the TASK_TIMEOUT config to set a global timeout. You can set it via an environment variable or in ansible.cfg. There’s no way to set that config in a play(book) or role, though.

From your writing, ansible.cfg sounds like a good place to add this.

2 Likes

HI felixfontein,

Thanks for replying

With your suggestion i tried with TASK_TIMEOUT -

 cat /etc/ansible/ansible.cfg
# Since Ansible 2.12 (core):
# To generate an example config file (a "disabled" one with all default settings, commented out):
#               $ ansible-config init --disabled > ansible.cfg
#
# Also you can now have a more complete file by including existing plugins:
# ansible-config init --disabled -t all > ansible.cfg

# For previous versions of Ansible you can check for examples in the 'stable' branches of each version
# Note that this file was always incomplete  and lagging changes to configuration settings

# for example, for 2.9: https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg
[defaults]
task_timeout=30

But it is not aborting the task even if it is running for more than 30sec.

TASK_TIMEOUT[]

Description:

Set the maximum time (in seconds) for a task action to execute in. Timeout runs independently from templating or looping. It applies per each attempt of executing the task’s action and remains unchanged by the total time spent on a task. When the action execution exceeds the timeout, Ansible interrupts the process. This is registered as a failure due to outside circumstances, not a task failure, to receive appropriate response and recovery process. If set to 0 (the default) there is no timeout.

Type:

integer

Default:

0

Version Added:

2.10

Ini:

Section:

[defaults]

Key:

task_timeout

Environment:

Variable:

[ANSIBLE_TASK_TIMEOUT]

The above i found out from ansible documentation and not able to get the result as expected.

TASK_TIMEOUT is not working as expected - Task timeout

It does work for me: I created an ansible.cfg file:

[defaults]
task_timeout=2

next to a test playbook:

- hosts: localhost
  gather_facts: false
  tasks:
    - ansible.builtin.command: /bin/sh -c 'sleep 10'

When running the playbook, I get:

[ERROR]: Task failed: Action failed: The ansible.builtin.command action failed to execute in the expected time frame (2) and was terminated
1 Like

The Issue I’m Facing

I’m working with complex Ansible deployments that involve:

  • Container image operations (load, tag, push)
  • Microservice deployments (Longhorn, MongoDB, Keycloak)
  • Many tasks across multiple playbooks/roles

These operations often take unpredictable amounts of time, and I need a global timeout mechanism that will apply to ALL tasks regardless of their type. I can’t practically modify each individual task to add timeouts.

What I’m Looking For

I need a solution that:

  1. Applies globally across all playbooks and roles
  2. Works for ALL task types, not just shell/command tasks
  3. Can be configured in one place (like ansible.cfg)
  4. Works with Ansible Core 2.17

Why the Example is Insufficient

The example you provided only demonstrates timeout working with a shell command:

- ansible.builtin.command: /bin/sh -c 'sleep 10'

But my deployments include many different module types:

  • Through our ansible play we are bringing up rke2-server as well, complete rke2 orchestration along with microservices
  • docker_image or containers.podman.podman_image
  • k8s
  • Various service modules
  • Network and API request modules

What I’m Looking For Specifically

Is there a configuration option in Ansible (possibly in ansible.cfg) that will apply a timeout to ALL tasks regardless of the module type? If the task_timeout parameter only works for certain module types, what alternatives do I have for establishing global timeouts?

I need to ensure tasks don’t hang indefinitely when:

  • A container registry is slow to respond
  • Network connectivity is intermittent
  • A microservice deployment is stalled
  • API endpoints are responding slowly

Testing Needed

Could you test if the task_timeout setting works for non-shell tasks like:

  • Container operations
  • Kubernetes deployments
  • API calls

Or suggest an alternative approach that would work for my complex deployment scenario?

Thanks for your response

The task timeout feature works at the core engine level, so ‘module type’ should not be an issue. The timeout is implemented via SIGALARM , which can be overridden and … the podman collection does (they seem to override most signals).

1 Like

Hi bcoca,

Thanks for responding let me share my sample ansible task here -

  • name: Scale down job pods
    shell: |
    kubectl delete jobs --selector=parent=cronjobmongo -n {{ mongo_image.project }}
    ignore_errors: true

  • name: Wait until job-created pods are terminated
    shell: |
    kubectl get pods -n {{ mongo_image.project }} --selector=job-name -o jsonpath=‘{.items[*].metadata.name}’
    register: job_pods
    retries: 10
    delay: 10
    until: job_pods.stdout == “”
    ignore_errors: true

  • name: Delete MongoDB backup PVC
    shell: |
    kubectl delete pvc mongoutil-mongodump -n {{ mongo_image.project }}
    ignore_errors: true

  • name: Uninstall replicaset-mongo
    shell: |
    helm uninstall mongodb-cron -n {{ mongo_image.project }}
    ignore_errors: true

like above sinppet i have lot of ansible roles, suppose here pvc deletion got stuck time, if i had a global timeout it would timeout the ansible task and move to next. I have lot of ansible plays i cannot go and append in all tasks [–timeout=120s]

So, please suggest is there any other way to set global task timeout, one place where we can set so that task will timeout when certain thershold point is reached

You can adjust it via configuration on the control node as suggested replacing any need to apply it at runtime.

It is possible for modules to ignore the signal but that functionality is the same regardless of how you pass the global timeout.

Testing is key in setting the right the setting value.

[defaults]
task_timeout=2

By adding above lines is working only for the below kind of task which means for shell commands

  • hosts: localhost
    gather_facts: false
    tasks:
    • ansible.builtin.command: /bin/sh -c ‘sleep 10’

The ansible task which i previously shared for those the task_timeout is not working. That where i am concerned

I looked for the blogs , i couldn’t find much helpful. Can u suggest any approach so i can follow it for all my ansible roles.

Change your usage of shell to use command to avoid a subshell waiting for the command to complete before satisfying the subshell.

Are you looking for a timeout because the commands you send are hanging indefinitely? You seem to using a lot of kubectl commands via shell. Why aren’t you using the kubernetes.core.k8s module (and collection)?

The framework we are following like this for many roles. There are few ansible roles using kubectl commands not all. I just posted this bit. Can you please confirm if there is any global task timeout, because ansible play will be stuck sometimes not everytime, i want ansible task to timeout with thershold i set. Introduced task_timeout in ansible.cfg even though not woring. There are so many roles, i cannot append in each task for timeout so, if global task timeout is supported for our ansible 2.17 core. Please help me with this. I looked into lot of blogs, but none did help us out in achieveing global task timeout.

as above suggested by felix, it will work for only shell commands not our module related ansible task.

Please give us the conclusion.

Thanks

Reiterating from my response above:

  • YES, there is a global task timeout and 'it works’TM
  • it is based on SIGALARM
  • The collection you are using overrides SIGALARM, effectively breaking the feature
1 Like

Hi bcoca,

Can u let me know how i can use this, can i define it in one place like inventory or ansible.cfg because i have more than 100 ansible roles, i cannot go to individual role and add as it is not feasible.

Help me with any sample to use this globally, i want to define in one place such that it is applicable for all ansible roles present.

@felixfontein did in Looking for a Way to Set a Global Task Timeout in Ansible - #4 by felixfontein

It shows how to do it in ansible.cfg which can be applied in multiple places depending on you run your various roles and playbooks.

1 Like

Yes but it is working only for shell commands.

For my use case it is not working as above i shared a one of the sample ansible task, like that we have more than 100 roles

If the things you are running don’t respect the SIGALRM signal then the timeout won’t work as @bcoca pointed out. No amount of changing the setting will alter the behavior in 1 or 100 roles.

You can set it for any run of ansible or ansible-playbook in a variety of ways as documented in Ansible Configuration Settings — Ansible Community Documentation

1 Like

It’s working for me, even for modules in the containers.podman collection. Can you give a concrete example that isn’t working for you?

Right now for testing purpose trying like this -

cat /etc/ansible/ansible.cfg
[defaults]
task_timeout=2

Below is sample ansible task i am trying to verify task_timeout, but not working

cat test/tasks/test.yaml

  • name: Execute a long-running task with a timeout
    hosts: all
    tasks:
    • name: Run a command with a timeout
      command: sleep 1200

What’s the output of ansible-config dump --only-changed, and can you share the playbook run with -vv? When you run your playbook with -vv, you should see what config file it’s using, like this:

ansible-playbook [core 2.19.0.dev0] (detached HEAD f5a85493c1) last updated 2025/05/14 07:12:54 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/shertel/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/shertel/projects/dev/lib/ansible
  ansible collection location = /home/shertel/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/shertel/.local/bin/ansible-playbook
  python version = 3.12.1 (main, Dec 18 2023, 00:00:00) [GCC 13.2.1 20231011 (Red Hat 13.2.1-4)] (/usr/bin/python3.12)
  jinja version = 3.1.2
  pyyaml version = 6.0.1 (with libyaml v0.2.5)
Using /etc/ansible/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: test_timeout.yml *********************************************************************************************************************************************************************************
1 plays in test_timeout.yml

PLAY [Execute a long-running task with a timeout] **********************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
task path: /home/shertel/projects/dev/test_timeout.yml:1
ok: [localhost]

TASK [Run a command with a timeout] ************************************************************************************************************************************************************************
task path: /home/shertel/projects/dev/test_timeout.yml:5
[ERROR]: Task failed: Action failed: The command action failed to execute in the expected time frame (2) and was terminated
Origin: /home/shertel/projects/dev/test_timeout.yml:5:5

3   tasks:
4
5   - name: Run a command with a timeout
      ^ column 5

fatal: [localhost]: FAILED! => {"changed": false, "msg": "The command action failed to execute in the expected time frame (2) and was terminated", "timedout": {"frame": "Interrupted at <frame at 0x7f8ba1d04340, file '/usr/lib64/python3.12/selectors.py', line 415, code select> called from <frame at 0x7f8ba1c84740, file '/home/shertel/projects/dev/lib/ansible/executor/task_executor.py', line 643, code _execute_internal>", "period": 2}}

PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

ansible-playbook -i inventory test.yaml -vv
ansible-playbook 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [‘/export/home/virtuora/.ansible/plugins/modules’, ‘/usr/share/ansible/plugins/modules’]
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 3.9.13 (main, Nov 9 2022, 13:16:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)]
Using /etc/ansible/ansible.cfg as config file
Skipping callback ‘actionable’, as we already have a stdout callback.
Skipping callback ‘counter_enabled’, as we already have a stdout callback.
Skipping callback ‘debug’, as we already have a stdout callback.
Skipping callback ‘dense’, as we already have a stdout callback.
Skipping callback ‘dense’, as we already have a stdout callback.
Skipping callback ‘full_skip’, as we already have a stdout callback.
Skipping callback ‘json’, as we already have a stdout callback.
Skipping callback ‘minimal’, as we already have a stdout callback.
Skipping callback ‘null’, as we already have a stdout callback.
Skipping callback ‘oneline’, as we already have a stdout callback.
Skipping callback ‘selective’, as we already have a stdout callback.
Skipping callback ‘skippy’, as we already have a stdout callback.
Skipping callback ‘stderr’, as we already have a stdout callback.
Skipping callback ‘unixy’, as we already have a stdout callback.
Skipping callback ‘yaml’, as we already have a stdout callback.

PLAYBOOK: test.yaml ****************************************************************************************************************************
1 plays in test.yaml

PLAY [localhost] *******************************************************************************************************************************
META: ran handlers

TASK [Run a longer task with its own timeout] **************************************************************************************************
task path: /export/home/virtuora/sprint-24/sprint24_vxm-2.0-Beta/test.yaml:4
changed: [127.0.0.1] => {“ansible_facts”: {“discovered_interpreter_python”: “/usr/libexec/platform-python”}, “changed”: true, “cmd”: [“sleep”, “10”], “delta”: “0:00:10.003917”, “end”: “2025-05-14 07:39:17.964962”, “rc”: 0, “start”: “2025-05-14 07:39:07.961045”, “stderr”: “”, “stderr_lines”: , “stdout”: “”, “stdout_lines”: }
META: ran handlers
META: ran handlers

PLAY RECAP *************************************************************************************************************************************
127.0.0.1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

cat /etc/ansible/ansible.cfg

[defaults]
task_timeout = 2

ansible-config dump --only-changed
no output for above command

please let me know if any other details is required. It should terminate the ansible task right after 2 seconds right but not happening

1 Like