Ansible之when条件语句

  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
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 作为背锅侠运维工作的基本流程 运维工具的分类 : ansible的模块化: ansible密钥登陆 ansible...
    二郎5阅读 4,149评论 0 10
  • ###### Ansible总结 ##### 运维工作: 系统安装(物理机、虚拟机)-->程序包安装、配置、服务启...
    二郎5阅读 2,021评论 0 4
  • Puppet理论定义: Puppet 是一个跨平台的集中化配置管理系统,它使用自有的描述语言,可管理配置文件、用户...
    属于你的世界阅读 957评论 0 2
  • 一、高可用集群 (一)提升系统高可用性的解决方案:冗余(redundant) 工作模式active/passive...
    哈喽别样阅读 1,719评论 2 5
  • 人最大的错误 就是用健康做赌注 换取身外之物 有人换名 有人换利 有人换权 有人换地 换来了会咋样 还不是到医院去...
    旖旎i阅读 188评论 2 12