Ansible_處理失敗的任務


一、Ansible處理任務失敗

1、管理play中任務錯誤

1️⃣:Ansible評估任務的返回代碼,從而確定任務是成功還是失敗

2️⃣:通常而言,當任務失敗時,Ansible將立即在該主機上中止play的其余部分並且跳過所有后續任務,但有些時候,可能希望即使在任務失敗時也繼續執行play

2、忽略任務失敗

1️⃣:默認情況下,任務失敗時play會中止。不過,可以通過忽略失敗的任務來覆蓋此行為。可以在任務中使用ignore_errors關鍵字來實現此目的

  • 演示實例:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: install httpd
          yum:
            name: packages      //沒有這個包
            state: present
          ignore_errors: yes     //可選{yes、no}
    
        - name: shoe some massage
          debug:
            msg: "hello word"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [install httpd] ******************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": false, "failures": ["No package packages available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
    ...ignoring         //已經忽略這個任務出錯
    
    TASK [shoe some massage] **************************************************************************************************************************************************
    ok: [client.example.com] => {
        "msg": "hello word"
    }
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1     

3、任務失敗也強制執行處理程序(handlers)

1️⃣:在play中設置force_handlers: yes關鍵字,則即使play因為后續任務失敗而中止也會調用被通知的處理程序(force:促使,推動)

  • 演示實例:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      force_handlers: yes     //可選{yes、no}
      tasks:
        - name: install httpd
          shell: ls        //這條命令一定會執行成功,從而保證handlers處理程序一定會被觸發
          notify:
            - massage
    
        - name: install  httpd
          yum:
            name: packages       //沒有這個包,肯定會出錯
            state: present
    
      handlers:
        - name: massage
          debug:
            msg: "hello word"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [install httpd] ******************************************************************************************************************************************************
    changed: [client.example.com]
    
    TASK [install  httpd] *****************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"changed": false, "failures": ["No package packages available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
    
    RUNNING HANDLER [massage] *************************************************************************************************************************************************
    ok: [client.example.com] => {
        "msg": "hello word"
    }
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

2️⃣:處理程序會在任務報告changed結果時獲得通知,而在任務報告okfailed結果時不會獲得通知

4、指定任務失敗的條件

1️⃣:在任務中使用failed_when關鍵字來指定表示任務已失敗的條件;通常與命令模塊搭配使用,這些模塊可能成功執行了某一命令,但命令的輸出可能指示了失敗

  • 演示實例一:使用failed_when關鍵字
     //查看使用的腳本
    [root@localhost project]# cat files/test.sh 
    #!/bin/bash
    cat /root       //這句肯定會出錯
    echo "hello word"
     //注意:在playbook中執行腳本會以最后一個命令作為錯誤判斷標准,中間錯誤命令不會影響整體的出錯,同樣也不會因為中間出錯而報錯
    
     //查看playbook,執行一次看是否成功
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      tasks:
        - name: test
          script:
            files/test.sh 
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    	ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    changed: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
     //這樣無法判斷是否都執行成功
    
     //添加任務失敗判斷語句
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      tasks:
        - name: test
          script:
            files/test.sh 
          register: result
          failed_when: "'Is a directory' in result['stdout']"
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"changed": true, "failed_when_result": true, "rc": 0, "stderr": "Shared connection to client.example.com closed.\r\n", "stderr_lines": ["Shared connection to client.example.com closed."], "stdout": "cat: /root: Is a directory\r\nhello word\r\n", "stdout_lines": ["cat: /root: Is a directory", "hello word"]}
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

2️⃣:fail模塊也可用於強制任務失敗(主要是將雜亂的提示信息通過自己設置提示方式,達到簡單、明了的目的)

  • 演示實例二:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      tasks:
        - name: test
          script:
            files/test.sh 
          register: result
    
        - fail:
            msg: "There have a failed"
          when: "'Is a directory' in result['stdout']"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    changed: [client.example.com]
    
    TASK [fail] ***************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"changed": false, "msg": "There have a failed"}
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

5、指定何時任務報告“changed”結果

1️⃣:當任務對托管主機進行了更改時,會報告 changed 狀態並通知處理程序;如果任務不需要進行更改,則會報告ok並且不通知處理程序

2️⃣:使用changed_when關鍵字可用於控制任務在何時報告它已進行了更改

  • 演示實例一:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all 
      tasks:
        - name: test
          shell: echo "hello word"
    
     //執行后發現,每次都是changed
    [root@localhost project]# ansible-playbook playbook.yaml
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    changed: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
    
     //添加changed_when關鍵字,以便報告OK
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all 
      tasks:
        - name: test
          shell: echo "hello word"
          changed_when: false      //可選{true、false}
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    ok: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0    

3️⃣:根據通過已注冊變量收集的模塊的輸出來報告changed

  • 演示實例二:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all 
      tasks:
        - name: test
          command: echo "hello word"
          register: result
          changed_when: "'hello word' in result['stdout']"
    
      //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ****************************************************************************************************************************************************
    ok: [client.example.com]
    
    TASK [test] ***************************************************************************************************************************************************************
    changed: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
      //因為在result['stdout']中有hello word ,所以被認定為是true,所以就顯示changed

6、Ansible塊和錯誤處理

1️⃣:在playbook中,塊是對任務進行邏輯分組的子句,可用於控制任務的執行方式

2️⃣:通過塊,也可結合rescuealways語句來處理錯誤。如果塊中的任何任務失敗,則執行其rescue塊中的任務來進行恢復

3️⃣:在block子句中的任務以及rescue子句中的任務(如果出現故障)運行之后,always子句中的任務運行

4️⃣:總結:

  • block:定義要運行的主要任務
  • rescue:定義要在block子句中定義的任務失敗時運行的任務
  • always:定義始終都獨立運行的任務,不論blockrescue子句中定義的任務是成功還是失敗

5️⃣:演示: 

  • 演示實例一:當只有block和rescue,且block語句執行成功時,只執行block語句而不執行rescue語句(rescue:營救、救援)
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              shell: echo "hello word"
    
          rescue:
            - name: rescue
              shell: ls /root
    
     //執行play
    [root@localhost project]# ansible-playbook --syntax-check playbook.yaml 
    
    playbook: playbook.yaml
    [root@localhost project]# an
    anacron             ansible-config      ansible-console     ansible-galaxy      ansible-playbook    ansible-test        
    ansible             ansible-connection  ansible-doc         ansible-inventory   ansible-pull        ansible-vault       
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    changed: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
     //可以發現,只執行了block語句,並沒有執行rescue語句

 

  • 演示實例二:當只有block和rescue,且block語句執行失敗時,不執行block語句而執行rescue語句
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              command: cat /        //這句肯定會失敗
    
          rescue:
            - name: rescue
              shell: ls /root
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": true, "cmd": ["cat", "/"], "delta": "0:00:00.005350", "end": "2020-09-08 10:59:18.381699", "msg": "non-zero return code", "rc": 1, "start": "2020-09-08 10:59:18.376349", "stderr": "cat: /: Is a directory", "stderr_lines": ["cat: /: Is a directory"], "stdout": "", "stdout_lines": []}
    
    TASK [rescue] *************************************************************************************************************************************************************
    changed: [client.example.com]
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   
     //可以看出,block語句執行失敗而執行了rescue語句

 

  • 演示實例三:當block語句、rescue語句和always語句都有時,無論block語句是否失敗,always語句總是執行
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              command: cat /
    
          rescue:
            - name: rescue
              shell: ls /root
              
          always:
            - name: always
              debug:
                msg: "This is my test"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": true, "cmd": ["cat", "/"], "delta": "0:00:00.008993", "end": "2020-09-08 11:05:47.816489", "msg": "non-zero return code", "rc": 1, "start": "2020-09-08 11:05:47.807496", "stderr": "cat: /: Is a directory", "stderr_lines": ["cat: /: Is a directory"], "stdout": "", "stdout_lines": []}
    
    TASK [rescue] *************************************************************************************************************************************************************
    changed: [client.example.com]
    
    TASK [always] *************************************************************************************************************************************************************
    ok: [client.example.com] => {
        "msg": "This is my test"
    }
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   

6️⃣:block中的when條件也會應用到其rescuealways子句(若存在)

  • 演示實例一:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              command: echo "hello word"         //該語句沒有錯誤
              when: ansible_facts['distribution'] == "CentOS"      //條件判斷出錯會導致block語句不會執行
    
          rescue:
            - name: rescue
              shell: ls /root
              
          always:
            - name: always
              debug:
                msg: "This is my test"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"msg": "The conditional check 'ansible_facts['distribution'] == \"CentOS\"' failed. The error was: error while evaluating conditional (ansible_facts['distribution'] == \"CentOS\"): 'dict object' has no attribute 'distribution'\n\nThe error appears to be in '/root/project/playbook.yaml': line 7, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      block:\n        - name: block\n          ^ here\n"}
    
    TASK [rescue] *************************************************************************************************************************************************************
    changed: [client.example.com]
    
    TASK [always] *************************************************************************************************************************************************************
    ok: [client.example.com] => {
        "msg": "This is my test"
    }
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0    

 

  • 演示實例二:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              command: echo "hello word"
              when: ansible_facts['distribution'] == "CentOS"
    
          rescue:
            - name: rescue
              shell: ls /root
              when: ansible_facts['distribution_major_version'] == "7"    //這句when語句會執行失敗,導致rescue語句不會執行
              
          always:
            - name: always
              debug:
                msg: "This is my test"
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"msg": "The conditional check 'ansible_facts['distribution'] == \"CentOS\"' failed. The error was: error while evaluating conditional (ansible_facts['distribution'] == \"CentOS\"): 'dict object' has no attribute 'distribution'\n\nThe error appears to be in '/root/project/playbook.yaml': line 7, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      block:\n        - name: block\n          ^ here\n"}
    
    TASK [rescue] *************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"msg": "The conditional check 'ansible_facts['distribution_major_version'] == \"7\"' failed. The error was: error while evaluating conditional (ansible_facts['distribution_major_version'] == \"7\"): 'dict object' has no attribute 'distribution_major_version'\n\nThe error appears to be in '/root/project/playbook.yaml': line 12, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      rescue:\n        - name: rescue\n          ^ here\n"}
    
    TASK [always] *************************************************************************************************************************************************************
    ok: [client.example.com] => {
        "msg": "This is my test"
    }
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=1    ignored=0   
     //可以看出,block語句和rescue語句都沒執行
    實例二

     

 

  • 演示實例三:
     //查看playbook
    [root@localhost project]# cat playbook.yaml 
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: test 
          block:
            - name: block
              command: echo "hello word"
    
          rescue:
            - name: rescue
              shell: ls /root
              
          always:
            - name: always
              debug:
                msg: "This is my test"
              when: ansible_facts['distribution_version'] == "8"   //when條件儲出錯沒回導致always語句執行失敗
    
     //執行play
    [root@localhost project]# ansible-playbook playbook.yaml 
    
    PLAY [all] ****************************************************************************************************************************************************************
    
    TASK [block] **************************************************************************************************************************************************************
    changed: [client.example.com]
    
    TASK [always] *************************************************************************************************************************************************************
    fatal: [client.example.com]: FAILED! => {"msg": "The conditional check 'ansible_facts['distribution_version'] == \"8\"' failed. The error was: error while evaluating conditional (ansible_facts['distribution_version'] == \"8\"): 'dict object' has no attribute 'distribution_version'\n\nThe error appears to be in '/root/project/playbook.yaml': line 15, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      always:\n        - name: always\n          ^ here\n"}
    
    PLAY RECAP ****************************************************************************************************************************************************************
    client.example.com         : ok=1    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 
    實例三

     

  • 注意:block執行會成功的話,如果用when條件判斷,即使判斷條件會成功,但block語句任然會失敗,而去執行rescue語句

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM