ansible语法ignore_errors handlers when block rescue always loop

文章目录

    • ansible语法
      • firewalld和template
        • firewalld模块简单使用
        • template模块使用
          • 测试
      • playbook语法
        • 错误处理
        • handlers任务
          • 测试
          • 执行结果分析(忽略默认任务)
          • 总结
        • when条件判断
          • 测试
        • block任务块
          • 测试
          • 分析流程
        • loop循环
          • 测试
      • 加密和解密
          • 命令参数
          • 测试

ansible语法

firewalld和template

firewalld模块简单使用

  • firewalld模块参数

    • port 端口/协议

      • 80/tcp 80端口放行tcp协议
    • permanent 是否永久设置

      • bool值类型
    • immediate 是否马上生效

      • bool值类型
    • state 状态

      • enabled 添加防火墙规则

        = state #具体参数说明
        Enable or disable a setting.
        For ports: Should this port accept (enabled) or reject (disabled)
        connections.
        The states present' andabsent’ can only be used in zone level
        operations (i.e. when no other parameters but zone and state are set).
        (Choices: absent, disabled, enabled, present)
        type: str

vim ~/ansible/firewall.yml   #写下剧本  当前目录下有主机清单文件
===============================
---
- hosts: test
  tasks:
    - name: 安装防火墙
      yum: #调用yum模块
        name: firewalld
        state: present     #安装
    - name: 开启防火墙
      service:
        name: firewalld
        state: started
        enabled: yes      #开机自启
    - name: 设置防火墙
      firewalld: #调用firewalld模块
        port: 80/tcp        #80端口放行tcp
        permanent: yes      #永久设置
        immediate: yes      #马上生效
        state: enabled      #添加防火墙规则
===============================
ansible-playbook firewall.yml   #运行
PLAY [test] *********************

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

TASK [安装防火墙] ***********   #任务一 本来就有 所以是ok
ok: [node1]

TASK [开启防火墙] ***************#任务二 本来就开着  所以是ok
ok: [node1]

TASK [设置防火墙] ******************#任务三  设置成功   返回changed状态码
changed: [node1]

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


template模块使用

  • 作用
    • 拷贝控制端文件到被控制端
  • 和copy模块的区别
    • 可以拷贝过去不同的文件(对于不同主机来说)
  • 执行过程
    1. 创建模板文件(里面有相对应的变量名)
    2. 通过template模块将模板文件发送过去
    3. 模板文件里面的变量会自动替换
测试
mkdir ~/ansible/template
vim ~/ansible/template/index.html  #创建模板文件
==================================================================
Welcome to {{ansible_hostname}} on {{ansible_ens33.ipv4.address}}
==================================================================

vim ~/ansible/template.yml  #写template模块的测试剧本
========================================================
---
- hosts: webserver
  tasks:
          - name: 使用template模块
            template:
                    src: ~/ansible/template/index.html
                    dest: /tmp/Exclusive_file
===========================================================

#执行剧本
ansible-playbook template.yml

PLAY [webserver] *********

TASK [Gathering Facts] ***************
ok: [node3]
ok: [node4]

TASK [使用template模块] ********
changed: [node4]
changed: [node3]

PLAY RECAP ********
node3                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node4                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
#执行成功

ansible webserver -m shell -a "cat /tmp/Exclusive_file"  #查看下内容

node3 | CHANGED | rc=0 >>
Welcome to web1 on 192.168.4.13    #变量分别被web1 和192.168.4.13替换

node4 | CHANGED | rc=0 >>
Welcome to web2 on 192.168.4.14    #两个主机内容是不一样的

#测试成功

playbook语法

错误处理

ansible-playbook执行顺序是自上而下的 默认情况下 如果哪个任务执行失败了 下面的任务就不执行了

vim ~/ansible/debug.yml
=====================================
---
- hosts: test
  gather_facts: false                  #为了下面第一个debug模块报错 将gathering facts任务取消
  tasks:
          - debug:
                  msg: "主机名是:{{ansible_hostname}}"
          - name: 我是报错任务下的第一个任务
            ping:                                 #用ping模块测试
========================================
ansible-playbook debug.yml #执行

PLAY [test] ******

TASK [debug] *********
fatal: [node1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_hostname' is undefined\n\nThe error appears to be in '/root/ansible/debug.yml': line 5, column 13, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n          - debug:\n            ^ here\n"}

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

#只有debug任务被执行了      第二个ping模块任务并没有执行

说明默认情况下 如果剧本某个任务出错了 下面的任务是不会执行了


这时候 就可以使用ignore_errors来忽略错误

vim ~/ansible/debug.yml   #还是上面那个剧本
================================================
---
- hosts: test
  gather_facts: false                 
  ignore_errors: yes                       #添加这个属性并设置为true
  tasks:
          - debug:
                  msg: "主机名是:{{ansible_hostname}}"
           #ignore_errors: yes                               #这里也可以添加 也能使任务顺利执行
          - name: 我是报错任务下的第一个任务
            ping:                                 #用ping模块测试
==================================================

ansible-playbook debug.yml   #执行

PLAY [test] *********

TASK [debug] *********
fatal: [node1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_hostname' is undefined\n\nThe error appears to be in '/root/ansible/debug.yml': line 6, column 13, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n          - debug:\n            ^ here\n"}
...ignoring

TASK [我是报错任务下的第一个任务] *******                 #执行了!!!
ok: [node1]

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

**上面这个案例中 在剧本的play中添加了ignore_errors参数并设置为true 最终使得报错任务下面的任务能够得到执行 **

ignore_errors能够使得报错剧本执行全部任务 在不同地方添加作用也不同 上面案例中添加到play中 使得整个play中所有的任务的报错都能够被忽略 如果添加到play中的单个任务中 那么只会针对单个任务忽略报错情况(这时其他任务报错还是会导致剧本下面无法执行)

handlers任务

  • 剧本中tasks用来定义一定会执行的任务 handlers定义的任务需要被触发才能执行
  • handlers中的任务需要被tasks中的任务添加notify属性来指定触发 触发条件是指定的任务必须返回的是CHANGED状态
  • notify后面跟的内容需要跟handlers中的任务的name属性相同
  • 多个任务notify触发同一个handlers任务 只会执行一次
  • handlers任务在所有其他任务都执行后才执行
==================================#伪代码
---
- hosts: xxx
  tasks:
    - 任务1
      notify: 任务5
    - 任务2
  handlers:
    - 任务5
    - 任务6
===================================

任务5只会在任务1执行后且返回CHANGED的情况下才会执行


测试
vim ~/ansible/handlers.yml
===============================
---
- hosts: test
  handlers:           #handlers写在上面 测试handlers任务需要等待其他任务执行完毕
    - name: jihuo
      ping:
    - name: zaicijihuo
      shell: "echo zaicijihuo"
  tasks:
    - name: create directory
      file:
        path: /tmp/parents/subdir  #指定目录
        state: directory       #创建目录
      notify: jihuo                #触发handlers任务中的描述为激活的任务
    - name: create directory too  #再次执行 使得状态是SUCCESS
      file:
        path: /tmp/parents/subdir
        state: directory
      notify: zaicijihuo         #触发描述为再次激活的任务
    - name: touch file            #测试多次触发jihou是否执行多次 还有执行顺序测试
      file:
        path: /tmp/parents/1.txt
        state: touch
      notify: jihuo

===============================
ansible-playbook handlers.yml   #执行

PLAY [test] ********

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

TASK [create directory] *************
changed: [node1]

TASK [create directory too] *********
ok: [node1]

TASK [touch file] *****************
changed: [node1]

RUNNING HANDLER [jihuo] **********
ok: [node1]

PLAY RECAP ***************
node1                      : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

执行结果分析(忽略默认任务)
  1. 执行create dircectory任务 CHANGED返回值 激活 jihuo任务
  2. 执行create directory任务 因为目录以及存在 所以SUCCESS返回值 没有激活
  3. 执行touch file 任务 CHANGED返回值 激活 jihou任务
  4. jihuo任务被触发两次但是只执行1次 zaicijihuo任务没有被触发 所以没有执行
总结

经上面案例可知

  • 只有当任务返回状态为CHANGED才能触发handlers中对应任务
  • handlers中的任务需要等待其他任务执行完毕
  • 多次触发只执行一次
  • notify的值要和对应被触发任务name值对应上

when条件判断

语言中判断语句if 剧本中关键词是when

=============================#伪代码
---
- hosts: xxx
  tasks:
    - name: 任务1
      模块名: 
        参数: 值
      when: 变量名1 == 变量名2 and 变量名3 != 常数1 or 变量名4 > 常熟2    #判断式
      											#只当为真执行任务
      											#变量不要使用{{}} 直接写上去
===============================
  • 判断式为真执行相对应的任务 (只有任务区域有when)
  • 常见条件操作符: == != > >= < <=
  • 多个条件 and or 来连接
  • 变量不要用{{}}
测试
vim ~/ansible/when_test1.yml
=================================
---
- hosts: test
  tasks:
    - name: check memory size
      service:
        name: NetworkManager
        state: stopped
      when: ansible_memfree_mb < 700
==================================
ansible-playbook when_test1.yml  #执行
#执行成功

#将when的位置移动到play位置
vim ~/ansible/when_test2.yml
=====================================
---
- hosts: test
  tasks:
    - name: test
      ping:
  when: 1 > 5           #为假
=====================================
ansible-playbook when_test2.yml  #执行

ERROR! 'when' is not a valid attribute for a Play

The error appears to be in '/root/ansible/when_test2.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

---
- hosts: test
  ^ here
#看错误提示       play区域没有when参数

block任务块

  • block 将多个任务组合成一个任务组 方便少写判断条件
  • rescue 当block执行失败时 执行rescue中的任务
  • always 不管block任务执行是否成功 都会执行的任务

emmmmmm… try{}catch{}finally{}格式吗

测试
vim ~/ansible/block.yml
===============================
---
- hosts: test
  tasks:
    - block:
        - name: touch a file 1.txt
          file:
            name: /tmp/xyz/1.txt        #没有xyz目录 所以会失败
            state: touch
      rescue:                            #rescu会执行
        - name: touch a file 2.txt
          file:
            state: touch
            name: /tmp/2.txt
      always:                            #一直会被执行
        - name: touch a file 3.txt
          file:
            name: /tmp/3.txt
            state: touch
=================================
ansible-playbook block.yml  #执行

PLAY [test] ********

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

TASK [touch a file 1.txt] ********
fatal: [node1]: FAILED! => {"changed": false, "msg": "Error, could not touch target: [Errno 2] No such file or directory: b'/tmp/xyz/1.txt'", "path": "/tmp/xyz/1.txt"}

TASK [touch a file 2.txt] *******
changed: [node1]

TASK [touch a file 3.txt] **********
changed: [node1]

PLAY RECAP **********
node1                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

分析流程
  1. touch a file 1.txt 失败了
  2. touch a file 2.txt任务作为备用方案被执行了
  3. touch a file 3.txt任务执行了 (一定会执行 不管touch a file 1.txt任务是否成功)

突发想法 block中忽略错误 rescue是否执行?

直接在上面案例中修改即可 逻辑上不会有其他影响

vim ~/ansible/block.yml
==================================
---
- hosts: test
  tasks:
    - block:
        - name: touch a file 1.txt
          file:
            name: /tmp/xyz/1.txt        
            state: touch
          ignore_errors: yes            #加了忽略错误
      rescue:                           
        - name: touch a file 2.txt
          file:
            state: touch
            name: /tmp/2.txt
      always:                        
        - name: touch a file 3.txt
          file:
            name: /tmp/3.txt
            state: touch
===================================
ansible-playbook block.yml    #执行
PLAY [test] *************

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

TASK [touch a file 1.txt] **********
fatal: [node1]: FAILED! => {"changed": false, "msg": "Error, could not touch target: [Errno 2] No such file or directory: b'/tmp/xyz/1.txt'", "path": "/tmp/xyz/1.txt"}
...ignoring
                                             
TASK [touch a file 3.txt] ******              #直接执行任务3.txt了 rescue不执行了
changed: [node1]

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

结果是不会执行rescue了 忽略错误 所以block中的任务不管是否报错都视为成功

loop循环

循环。。。。没什么好说的 循环执行 减少代码量 每次循环变量不同

测试
vim ~/ansible/simple_loop.yml
=================================
---
- hosts: test
  tasks:
    name: 循环输出                                          ##变量前面要加都是item的
    shell: "echo 本次输出对象是:{{item.iname}} 年龄为:{{item.age}}"
    loop:                       #loop要和模块平级
      - {iname: 'tom',age: '22'} #冒号后面要加空格!!!
      - {iname: 'jack',age: '28'} #多个变量用{}括起来
=====================================


PLAY [test] ****************

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

TASK [循环输出] ***************
changed: [node1] => (item={'iname': 'tom', 'age': '22'})
changed: [node1] => (item={'iname': 'jack', 'age': '28'})

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

还有挺多循环提供变量的方法的 百度官方文档即可习得

加密和解密

ansible-vault可以用来加密敏感数据

命令参数
  • ansible-vault encrypt 加密文件 --vault-id 指定密码文件
  • ansible-vault view 查看加密文件 --vault-id 指定密码文件
  • ansible-vault decrypt 解密文件 --vault-id 指定密码文件
测试
echo 123456 > data.txt    #创建敏感数据文件data.txt
ansible-vault encrypt data.txt   #加密data.txt   输入密码为123456
cat data.txt  #正常查看
$ANSIBLE_VAULT;1.1;AES256
62386335373632386134353233656130626364323738353936623265303836633133363562306636
6464333739303361616533376534333434613936383562310a633033313761656261616164643036
39346633316263343837363630313866633536303031383064633966356662623436376239356565
6332313735613130350a383335616561343566646164396361303733643366643664323563646365
6538
#加密了 看不出原来是上面东西

ansible-vault view data.txt  #查看加密文件  输入密码123456
123456  #能看见里面的东西了

echo 123456 > secret.txt   #简便操作  不用输密码
ansible-vault rekey --vault-id=secret.txt  data.txt   #重新设置密码  旧密码由secret.txt文件提供  修改新密码为123
Rekey successful

ansible-vault decrypt data.txt --vault-id=secret.txt  #解密
Decryption successful

cat data.txt
123456  #现在能正常查看了

你可能感兴趣的:(Linux,ansible)