Ansible

Ansible之when条件语句

2018-05-18  本文已影响6人  GoGooGooo
  1. When语句
    有时候用户有可能需要某一个主机越过某一个特定的步骤.这个过程就可以简单的像在某一个特定版本的系统上少装了一个包一样或者像在一个满了的文件系统上执行清理操作一样.
    这些操作在Ansible上,若使用when语句都异常简单.When语句也含Jinja2表达式,
    第一个例子:

    tasks:
      - name: "shutdown Debian flavored systems"
        command: /sbin/shutdown -t now
        when: ansible_os_family == "Debian"
    

    如果你在RedHat系列linux系统执行,就不会被执行

    第二个例子:

    #cat copyfile.yml 
    ---
    - hosts: "`host`"
      user: "`user`"
      gather_facts: True
      tasks:
        - name: Copy file to client
          copy: src=/etc/ansible/test.txt dest=/usr/local/src
          when: ansible_os_family == "Debian"
        - include: add_user.yml
          when: ansible_os_family == "Debian"
    

    执行:
    ansible-playbook copyfile.yml -e "host=web user=root" --可以看到下面都skipping掉了

    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.26]
    ok: [10.0.90.25]
    TASK [Copy file to client] *****************************************************
    skipping: [10.0.90.25]
    skipping: [10.0.90.26]
    TASK [include] *****************************************************************
    skipping: [10.0.90.25]
    skipping: [10.0.90.26]
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=1    changed=0    unreachable=0    failed=0   
    10.0.90.26                 : ok=1    changed=0    unreachable=0    failed=0   
    

    以上yml中的任务都没有执行,因为我测试机器是CentOS系统!而条件是只有当系统是Debian类型的时候执行!
    PS:文件中的include模块后续会介绍。

    第三个例子:

    tasks:
      - shell: echo "only on Red Hat 6, derivatives, and later"
        when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int  >= 6
    

    意思是只有当系统是RedHat并且版本大于等于6的时候执行
    第三个例子:只有在server组或者名为server的这台服务器才执行

    - name: Copy file to client
          copy: src=/etc/ansible/test.txt dest=/usr/local/src
          when: "host=='server'"
    

    带管道的when语句

    tasks:
      - command: /bin/false
        register: result
        ignore_errors: True
      - command: /bin/something
        when: result|failed
      - command: /bin/something_else
        when: result|success
      - command: /bin/still/something_else
        when: result|skipped
    

    判断变量是否已经定义:
    如果一个变量不存在,你可以使用Jinja2的defined命令跳过或略过.例如:

    tasks:
        - shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
          when: foo is defined
        - fail: msg="Bailing out. this play requires 'bar'"
          when: bar is not defined
    
  2. debug模块
    Print statements during execution
    打印执行过程中的语句,通常用来调试编写好的playbook语句,

    Examples
    # Example that prints the loopback address and gateway for each host
    - debug: msg="System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"
    - debug: msg="System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
      when: ansible_default_ipv4.gateway is defined
    - shell: /usr/bin/uptime
      register: result
    - debug: var=result verbosity=2
    - name: Display all variables/facts known for a host
      debug: var=hostvars[inventory_hostname] verbosity=4
    

    生产环境遇到的一个案例:
    有2台server:
    第一台:10.0.90.25安装了nginx,
    第二台:10.0.90.26没有安装nginx
    现在我只想在没有安装nginx的server上做操作,需要通过when条件语句实现,如下:

    #cat test1.yml
    ---
    - hosts: web
      remote_user: root
      tasks:
        - name: ps
          shell: ps -ef | grep nginx | grep -v grep|wc -l
          register: nginx_num
        - debug: var=nginx_num
        - name: command 
          copy: src=/etc/ansible/server.xml dest=/root
          when: nginx_num.stdout == "0"
    

    PS:刚开始的时候,没有添加- debug: var=nginx_num这一项,结果执行的时候,总是skipping跳过,说明条件错误后来才使用debug模块调试
    执行结果:

    #ansible-playbook  test1.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    ok: [10.0.90.26]
    TASK [ps] **********************************************************************
    changed: [10.0.90.25]
    changed: [10.0.90.26]
    TASK [debug] *******************************************************************
    ok: [10.0.90.25] => {
        "nginx_num": {
            "changed": true, 
            "cmd": "ps -ef | grep nginx | grep -v grep|wc -l", 
            "delta": "0:00:00.008476", 
            "end": "2016-05-19 20:40:51.742088", 
            "rc": 0, 
            "start": "2016-05-19 20:40:51.733612", 
            "stderr": "", 
            "stdout": "3", 
            "stdout_lines": [
                "3"
            ], 
            "warnings": []
        }
    }
    ok: [10.0.90.26] => {
        "nginx_num": {
            "changed": true, 
            "cmd": "ps -ef | grep nginx | grep -v grep|wc -l", 
            "delta": "0:00:00.009458", 
            "end": "2016-05-19 20:40:51.754993", 
            "rc": 0, 
            "start": "2016-05-19 20:40:51.745535", 
            "stderr": "", 
            "stdout": "0", 
            "stdout_lines": [
                "0"
            ], 
            "warnings": []
        }
    }
    TASK [command] *****************************************************************
    skipping: [10.0.90.25]
    changed: [10.0.90.26]
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=3    changed=1    unreachable=0    failed=0   
    10.0.90.26                 : ok=4    changed=2    unreachable=0    failed=0
    

    可以看到跳过了10.0.90.25,只在10.0.90.26上执行了命令。
    范例1:

    #cat test2.yml 
    ---
    - hosts: 10.0.90.25
      user: root
      gather_facts: True
      tasks:
        - name: test debug module
          debug: msg="System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"
    #ansible-playbook test2.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    TASK [test debug module] *******************************************************
    ok: [10.0.90.25] => {
        "msg": "System 10.0.90.25 has uuid 564DB430-3121-EEE4-33F1-559FEF576AC9"
    }
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=2    changed=0    unreachable=0    failed=0
    

    范例2:

    #cat test3.yml 
    ---
    - hosts: 10.0.90.25
      user: root
      gather_facts: True
      tasks:
        - debug: msg="System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
          when: ansible_default_ipv4.gateway is defined
    说明:只有当远端server的gateway配置的情况下才执行,执行结果如下:
    #ansible-playbook test3.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    TASK [debug] *******************************************************************
    ok: [10.0.90.25] => {
        "msg": "System 10.0.90.25 has gateway 10.0.90.1"
    }
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=2    changed=0    unreachable=0    failed=0   
    将10.0.90.25网关配置去掉,再一次执行:
    #ansible-playbook test3.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    TASK [debug] *******************************************************************
    skipping: [10.0.90.25]
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=1    changed=0    unreachable=0    failed=0   
    

    说明:因为将远端server的网关配置去掉了,when条件不成立,就skipping了。

  3. notify和Handlers
    handlers 用于在发生改变时执行的操作。notify这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之的是仅在所有的变化发生完成后一次性地执行指定操作。比如多个resources指出因为一个配置文件被改动,所以apache需要重新启动,但是重新启动的操作只会被执行一次。在notify中列出的操作称为handler也即notify调用handler中定义的操作,Handlers也是一些task的列表,通过名字来引用,他们和一般的task并没有什么区别。Handlers是由通知者进行notify,如果没有被notify,handlers不会执行,不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次。
    注意:Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了,而且它会按照声明的顺序执行
    如下一个例子:
    自定义好httpd.conf配置文件(有变量),拷贝到/etc/httpd/conf目录,然后启动httpd,并设置开机自启动!

    #cat test3.yml 
    ---
    - hosts: web
      remote_user: root
      gather_facts: True
      vars:
        http_port: 80
        max_clients: 200
      tasks:
        - name: ensure apache is at the latest version
          yum: pkg=httpd state=latest
        - name: copy httpd config file to client 
          copy: src=/etc/ansible/httpd_test.config dest=/etc/httpd/conf/
          notify:
          - restart apache
        - name: ensure apache is running
          service: name=httpd state=started
      handlers:
        - name: restart apache
          service: name=httpd state=restarted
    

    执行:

    #ansible-playbook test3.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    ok: [10.0.90.26]
    TASK [ensure apache is at the latest version] **********************************
    changed: [10.0.90.26]
    changed: [10.0.90.25]
    TASK [copy httpd config file to client] ****************************************
    changed: [10.0.90.26]
    changed: [10.0.90.25]
    TASK [ensure apache is running] ************************************************
    ok: [10.0.90.26]
    ok: [10.0.90.25]
    RUNNING HANDLER [restart apache] ***********************************************
    changed: [10.0.90.26]
    changed: [10.0.90.25]
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=5    changed=3    unreachable=0    failed=0   
    10.0.90.26                 : ok=5    changed=3    unreachable=0    failed=0
    

    注:此处定义的notify是restart,就是安装好httpd并拷贝好配置文件之后。
    notify也可以是restarted、stopped、reloaded
    enabled=yes是表示设置httpd开机自启动。
    如果再次执行,就不会有任何改变了。因为httpd已经启动了

    #ansible-playbook test3.yml 
    PLAY ***************************************************************************
    TASK [setup] *******************************************************************
    ok: [10.0.90.25]
    ok: [10.0.90.26]
    TASK [ensure apache is at the latest version] **********************************
    ok: [10.0.90.25]
    ok: [10.0.90.26]
    TASK [copy httpd config file to client] ****************************************
    ok: [10.0.90.26]
    ok: [10.0.90.25]
    TASK [ensure apache is running] ************************************************
    ok: [10.0.90.26]
    ok: [10.0.90.25]
    PLAY RECAP *********************************************************************
    10.0.90.25                 : ok=4    changed=0    unreachable=0    failed=0   
    10.0.90.26                 : ok=4    changed=0    unreachable=0    failed=0
    
上一篇下一篇

猜你喜欢

热点阅读