Ansible shell ignore error

I am learning Ansible. I have a playbook to clean up resources, and I want the playbook to ignore every error and keep going on till the end , and then fail at the end if there were errors. I can ...

I found this to be helpful:

https://medium.com/opsops/anternative-way-to-handle-errors-in-ansible-245a066c340

In your task you want to register the task.

register: some_name

Then add ignore_errors: yes

Then use set_fact to get each register attribute:

- set_fact:
    success: '{{ not([e1, e2]|map(attribute="failed")|max) }}'

Then place this at the end of your block:

- name: Fail server build
  command: >
    bash scripts/test_file.sh
  when: success == false
  ignore_errors: yes

The block above would only be executed when success is false. The key is using ignore_errors and making a register. From the link I posted and from my testing the task attribute is registered if it fails or not.

Example output:

PLAY [localhost] ***********************************************************************************************

TASK [Gathering Facts] *****************************************************************************************
ok: [localhost]

TASK [Task 1 test] *********************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["bash", "scripts/unknown_file.sh"], "delta": "0:00:00.004343", "end": "2021-10-20 14:20:59.320389", "msg": "non-zero return code", "rc": 127, "start": "2021-10-20 14:20:59.316046", "stderr": "bash: scripts/unknown_file.sh: No such file or directory", "stderr_lines": ["bash: scripts/unknown_file.sh: No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Task 2 test] *********************************************************************************************
changed: [localhost]

TASK [set_fact] ************************************************************************************************
ok: [localhost]

TASK [Fail server build] ***************************************************************************************
changed: [localhost]

TASK [debug] ***************************************************************************************************
ok: [localhost] => {
    "success": false
}

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

Ansible Error handling – In this lesson, you will learn the different ways of how to handle failures in Ansible tasks by using the ignore_errors, force_handlers, Ansible blocks, Ansible rescue, and Ansible always directives in a playbook.

Contents

  • How Can You Handle Error In Ansible
  • Specifying Task Failure Conditions
  • Managing Changed Status
  • Using Ansible Blocks
  • Using Ansible Blocks With Rescue and Always Statement

How Can Error Handling Be Done In Ansible

Ansible plays and tasks are executed in the order they are defined in a playbook, and by default, if a task fails, the other tasks will not be executed in that order. However, this behavior can be changed with the use of a keyword called “ignore_errors: true“.

This keyword can be added to a play or a task as the case may be. If it is added to a play, it means that all the errors in the tasks associated to a play will be ignored. More so, if it is added to a task, it means all the errors in the task will be ignored.

Well, we learnt about handlers in one of our previous lessons, what about handlers? Yes, this is also applicable to handlers, handlers error can be handled by the keyword, “force_handlers:yes”.

If a task that is supposed to notify a handler fails, the handlers will not be executed. This behavior can also be changed by using the keyword, “force_handler: yes” .

As usual, let’s understand better with examples.

If we were to install the httpd package and the autofs package using a playbook, the name argument will consist of the “httpd” value and the “autofs” value.

Now, we are going to write a playbook, and we will intentionally make an error by making the name argument of autofs containing “autos“.

1. Create a playbook

[lisa@drdev1 ~]$ vim playbook7.yml
- name: Install basic package
  hosts: hqdev1.tekneed.com
  tasks:
     - name: install autofs
       yum:
         name: autos
         state: present
       ignore_errors: true

     - name: install httpd
       yum:
         name: httpd
         state: present

2. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook7.yml

PLAY [Install basic package] ***********************************************************
........

ansible error handling

This playbook we run should have resulted in an error or task failure, and the second task shouldn’t have run because the first task failed, but because we used the “ignore_errors” keyword, the task did not fail and the play run.

Also, remember that you can choose to use the “ignore_errors” keyword at a play level or at a task level. In our case, it was used at the task level.

Again, let’s see an example of how we can use the force_handlers keyword to forcefully run a task with handlers.

1. create a playbook

- name: restarting httpd using handlers
  hosts: hqdev1.tekneed.com
  force_handlers: yes
  tasks:
    - name: restart httpd
      service:
        name: httpd
        state: restarted
      notify: restart httpd

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

The force_handler directive will always force handlers to run whether it is called or not. Note that the keyword can only be used at a play level

2. Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook3.yml

PLAY [restarting httpd using handlers] ********************************
......

Because the force_handlers directive is set to yes, the handler will always run.

Specifying Task Failure conditions

Ansible may run a task/command successfully, however may be a failure due to the final result a user desires to get. In this sense, one can specify a condition for tasks to fail or in other words, you are at liberty to determine what a failure is.

Let’s see how this can be done by using the “failed_when” directive. The failed_when directive, from its word, simply means the task should fail when a condition is met or not met.

Let’s use the playbook below as an example,

[lisa@drdev1 ~]$ vim playbook5.yml
- name: Web page fetcher
  hosts: hqdev1.tekneed.com
  tasks:
    - name: connect to website
      uri:
        url: https://tekneed.com
        return_content: true
      register: output

    - name: verify content
      debug:
        msg: "verifying content"
      failed_when:
        - '"this content" not in output.content'
        - '"other content" not in output.content'

This is what this playbook will do. The uri module will interact with the webserver and fetch the page, https://www.tekneed.com.
More so, With the true value for the return_content argument, the body of the response of https://tekneed.com will be returned as content, and output will be captured with the aid of the register directive.

For the second task, the content “verifying content” will be printed by the debug module with the aid of the msg argument, and with the “failed_when” directive, the task will fail when the string, “this content” and “other content” is not in the captured output.

Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook5.yml

PLAY [Web page fetcher] ************************************************************
.......

Alternatively, the “fail” module can be used to specify when a task fails. This module can only be very useful if the “when” keyword is used to specify the exact failure condition.

Let’s use the same example we used above, but this time around use the “fail” module and “when” keyword

[lisa@drdev1 ~]$ vim playbook5.yml
- name: Web page fetcher
  hosts: hqdev1.tekneed.com
  tasks:
    - name: connect to website
      uri:
        url: https://tekneed.com
        return_content: true
      register: output

    - name: verify content
      fail:
        msg: "verifying content"
      when:
        - '"this content" not in output.content'
        - '"other content" not in output.content'

Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook5.yml

PLAY [Web page fetcher] ************************************************************
.......

Managing Changed Status

Managing a changed status can be useful in avoiding unexpected results while running a playbook. Some tasks may even report a changed status and nothing in the real sense has really changed. It could just be that information was retrieved.

In some cases, you may not want a task to result in a changed status. In this case, one needs to use the “changed_when: false” keyword. The playbook will only report “ok” or “failed” status, and will never report a changed status.

An example of such task can be seen below.

- name: copy in nginx conf
  template: src=nginx.conf.j2
            dest=/etc/nginx/nginx.conf

- name: validate nginx conf
  command: nginx -t
  changed_when: false

One can also specify a condition when a task should change, an example of such task is seen in the playbook below.

- name: Web page fetcher
  hosts: hqdev1.tekneed.com
  tasks:
    - name: connect to website
      uri:
        url: https://tekneed.com
        return_content: true
      register: output

    - name: verify content
      fail:
        msg: "verifying content"
      changed_when: "'success' in output.stdout"

Using Ansible Blocks

Blocks are used to group tasks, specific tasks that are related, and can be very useful with a conditional statement.

If tasks are grouped conditionally, and the conditions is/are true, all the tasks will be executed. You should also know that block is a directive in Ansible and not a module, hence the block directive and the when directive will be at the same indentation level.

Let’s see how blocks can be used with examples.

create a playbook

[lisa@drdev1 ~]$ vim playbook8.yml
- name: setting up httpd
  hosts: localhost
  tasks:
    - name: Install start and enable httpd
      block:
      - name: install httpd
        yum:
          name: httpd
          state: present
      - name: start and enable httpd
        service:
          name: httpd
          state: started
          enabled: true
      when: ansible_distribution == "Red Hat"

This playbook will group only two tasks in a block(install and enable httpd). The first task name is “install httpd” while the second task name is “start and enable httpd“. These tasks will only execute if the condition is true, which is, the OS ansible will execute against is/are Red Hat.

Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook8.yml

PLAY [setting up httpd] ********************************************************
.......

With this kind of playbook, if the condition fails, other tasks will not be executed. Let’s see how we can use block with rescue and always if we don’t want this type of condition.

Using Ansible block With rescue and always Statement

Apart from blocks being used to group different tasks, they can also be used specifically for error handling with the rescue keyword.

It works in a way that; if a task that is defined in a block fails, the tasks defined in the rescue section will be executed. This is also similar to the ignore_errors keyword.

More so, there is also an always section, this section will always run either the task fails or not. This is also similar to the ignore_errors keyword.

Let’s understand better with examples.

create a playbook.

[lisa@drdev1 ~]$ vim playbook9.yml
- name: setting up httpd
  hosts: localhost
  tasks:
    - name: Install the latest httpd and restart
      block:
        - name: install httpd
          yum:
            name: htt
            state: latest
      rescue:
        - name: restart httpd
          service:
            name: httpd
            state: started
        - name: Install autofs
          yum:
            name: autofs
      always:
        - name: restart autofs
          service:
            name: autofs
            state: started

This playbook will group four tasks in a block(install the latest httpd and restart).
The first task in the block section will fail because the name of the package is incorrect. However, the second and third tasks will run because they are in the rescue section. More so, the fourth task will run because it is in the always section.

Note that you can have as many tasks you want in the block section, rescue section or always section

Run the playbook

[lisa@drdev1 ~]$ ansible-playbook playbook9.yml

PLAY [setting up httpd] *********************************************************
......

Class Activity

create a playbook that contains 1 play with tasks using block, always and rescue statements

If you like this article, you can support us by

1. sharing this article.

2. Buying the article writer a coffee (click here to buy a coffee)

3. Donating to push our project to the next level. (click here to donate)

If you need personal training, send an email to info@tekneed.com

Click To Watch Video On Ansible Error Handling

RHCE EX294 Exam Practice Question On Ansible Error Handling

Suggested: Managing Layered Storage With Stratis – Video

Your feedback is welcomed. If you love others, you will share with others

In ansible if anyone of the task fails then it will stop the the entire execution of playbook or role.

So to avoid this problem we use ingnore_errors=True

ignore_errors=True

Error Handling In ansible Playbooks

If you mention ignore_errors=true at the end of the task , if the task fails also still the playbook or role will run.  It will execute the next task without taking care of task success or failure. If the task failure also it will go for next task and if the task success also it will go for execution next task.

So if you mention ignore_errors=true in any task ansible will go for execution of next task with out taking care of the task result.

Ex:

Playbook or role:
[root@localhost ~]# cat ignore_errors.yml 
---
- hosts: localhost
  tasks:
  - name: Stop httpd if already running
    service: name=httkd state=stopped
    ignore_errors: True

  - name: Stop httpd if already running
    service: name=httpd state=stopped
Output Log:
[root@localhost ~]# ansible-playbook ignore_errors.yml 

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Stop httpd if already running] *********************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Could not find the requested service httkd: host"}
...ignoring

TASK [Stop httpd if already running] *********************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

here you can see that first task is failed but still ansible is executing second task and the playbook is not failed.

so here you can see in the log first task it is ignoring errors. and its going for second task.

ignore_errors=False

by default ansible will consider task as ignore_errors=False so no need to mention this, but mention ignore_errors=True depends on your requirements.

  • ansible ignore errors
  • Error Handling In Playbooks
  • Error Handling In ansible Playbooks
  • ansible ignore errors true
  • ignore errors false
  • playbook ignore errors ansible
  • Error Handling In ansible Playbooks
  • ansible role ignore errors
  • ignore_errors

I’m trying to ignore a particular error message in playbook output is having below error message.

fatal: [192.168.0.1]: FAILED! => {«changed»: false, «failed»: true, «msg»: «Sending passwords in plain text without SSL/TLS is extremely insecure.. Query == CHANGE MASTER TO [‘MASTER_HOST=%(master_host)s’, ‘MASTER_USER=%(master_user)s’, ‘MASTER_PASSWORD=%(master_password)s’, ‘MASTER_LOG_FILE=%(master_log_file)s’, ‘MASTER_LOG_POS=%(master_log_pos)s’]»}

> Task: 
> - name: Setup Replication   
    become: true   
    mysql_replication:
>      login_host: "{{ slave_ip }}"
>      login_user: "user"
>      login_password: "***"
>      mode: changemaster
>      master_host: "{{ master_ip }}"
>      master_log_file: mysql-bin.000001
>      master_log_pos: 107
>      master_user: "{{ mysql_replicator_user }}"
>      master_password: "{{ mysql_replicator_password }}"

Any luck? how to achieve this?

EDITED: Reply to Marco Answer —
well that is the problem here, I would not know what error I might get. But I’m sure that if err msg contains «Sending passwords in plain text without SSL» then ignore if not and anyother error then don’t ignore. To explain in simple «Throw exception if error msg doesn’t contain -> ‘null’ or SSL.»

asked Apr 3, 2017 at 10:56

mannoj's user avatar

mannojmannoj

2311 gold badge2 silver badges6 bronze badges

There are a couple of options regarding error handling in Ansible. You could use ignore_errors: yes attribute on your task. If you don’t want to ignore all errors, you can specify what exactly constitutes an error using something like:

- name: task name
  module: arguments ...
  register: out
  failed_when: 'error message' in out.stderr 

If you want to add more complex failure checks, you can split error handling off into separate task like this:

- name: test
  shell: echo error; exit 123
  register: out
  ignore_errors: yes

- fail: msg="{{ out.stdout }}"
  when: "out.rc != 0 and 'error' not in out.stdout"

In this example first task fails with return code 123 and prints «error» on it’s standard output. This will be registered, but ignored. Second task analyzes output values and fails only if return code is different than zero AND standard output does NOT contain string «error».

You can read more details in Ansible documentation: https://docs.ansible.com/ansible/playbooks_error_handling.html

answered Apr 3, 2017 at 11:35

Marko Živanović's user avatar

2

I really wish ignore_errors wasn’t simple yes/no check. That would’ve make our life much more simpler. Recently I discovered this brilliant trick. With this method it’s possible to ignore certain known outputs. In this example we’re looking for Sending passwords in plain text without SSL text in registered variable. If we find the text, it’ll evaluate to 0. Then we’ll compare it to -1 which is return code of find function if string not found. Since 0 == -1 will evaluate to False ultimately our condition will be failed_when: False

On the other hand if string is not found, expression will be -1 == -1 => failed_when: True Be careful with this approach as you’ll be overriding default fail behavior of the module. So it’s best to combine with multiple conditions like exit code.

- name: Risky task
  command: echo "Sending passwords in plain text without SSL"
  register: result
  changed_when: false
  failed_when:
    # returns -1 if string not found
    - result.stdout.find("Sending passwords in plain text without SSL") == -1
    # best to combine additional checks like return code
    - result.rc != 0

I guess you could’ve use something like result.stdout.find("Sending passwords in plain text without SSL") != 0 or '"Sending passwords in plain text without SSL" not in result.stdout', but double negation makes it kinda harder to understand.

answered Aug 23, 2022 at 9:19

Shinebayar G's user avatar

Shinebayar GShinebayar G

1931 gold badge1 silver badge4 bronze badges

playbook.yml пытаемся установить не существующий пакет treeee и выводим echo

name:  Error find and control

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

   name: Tasks number2

    shell: echo Hellow world!

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml ignore_errors игнорим ошибки и выполняем следующие таски

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

name:  Error find and control

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: echo Hellow world!

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml дебаг ignore_errors

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

name:  Error find and control

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: ls la /var/

    register: results

   debug:

      var: results

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml failed_when

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

name: Test ansible

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: echo Hellow world

    register: results

    failed_when: «‘world’ in results.stdout»

   debug:

      var: results

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml failed_when result.rc

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

name: Test ansible

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: echo Hellow world

    register: results

    failed_when: result.rc == 0

#    failed_when: «‘world’ in results.stdout»

   debug:

      var: results

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml выполнится только там где есть file1.txt

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

name: Test ansible

  hosts: all

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: cat /home/secret/file1.txt

    register: results

   debug:

      var: results

   name: Tasks number3

    shell: echo Privet Man!

...

playbook.yml any_errors_fatal

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

name: Test ansible

  hosts: all

  any_errors_fatal : true

  become: yes

  tasks:

   name: Tasks number1

    yum: name=treeee state=present

    ignore_errors: yes

   name: Tasks number2

    shell: cat /home/secret/file71.txt

    register: results

   debug:

      var: results

   name: Tasks number3

    shell: echo Privet Man!

...

Понравилась статья? Поделить с друзьями:
  • Ansible error reading ssh protocol banner
  • Ann error has occurred please try again later
  • Aniboom error player что делать
  • Angular обработка ошибок
  • Angular material mat error