ansible的条件判断、迭代执行、tags

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

在ansible中支持条件判断,这使我们操作更加灵活

使用when进行条件测试

示例1:

将 testservers 组中的其中一台主机上的 httpd 服务卸载掉,另外主机不卸载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@node1 ansible] # ansible testservers -m shell -a 'rpm -q httpd'
192.168.100.131 | success | rc=0 >>
httpd-2.2.15-29.el6.centos.x86_64
 
192.168.100.132 | success | rc=0 >>
httpd-2.2.15-47.el6.centos.3.x86_64
 
[root@node1 ansible] # cat http.yml 
- hosts: testservers
   remote_user: root
   tasks:
   - name: uninstall httpd service
     yum: name=httpd state=absent
     when: ansible_nodename ==  "v2.lansgg.com"
     
[root@node1 ansible] # ansible-playbook http.yml 
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [uninstall httpd service] *********************************************** 
skipping: [192.168.100.132]
changed: [192.168.100.131]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=2    changed=1    unreachable=0    failed=0   
192.168.100.132            : ok=1    changed=0    unreachable=0    failed=0   
 
[root@node1 ansible] # ansible testservers -m shell -a 'rpm -q httpd'
192.168.100.132 | success | rc=0 >>
httpd-2.2.15-47.el6.centos.3.x86_64
 
192.168.100.131 | FAILED | rc=1 >>
package httpd is not installed
 
[root@node1 ansible] #

示例2:

也可以使用 or 进行 或 判断,这里将组内的两台主机的 httpd 服务都卸载,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@node1 ansible] # ansible testservers -m shell -a 'rpm -q httpd'
192.168.100.132 | success | rc=0 >>
httpd-2.2.15-47.el6.centos.3.x86_64
 
192.168.100.131 | success | rc=0 >>
httpd-2.2.15-29.el6.centos.x86_64
 
[root@node1 ansible] # cat http.yml 
- hosts: testservers
   remote_user: root
   tasks:
   - name: uninstall httpd service
     yum: name=httpd state=absent
     when: (ansible_nodename ==  "v2.lansgg.com" ) or ( ansible_all_ipv4_addresses[0] ==  '192.168.100.132' )
     
[root@node1 ansible] # ansible-playbook http.yml 
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [uninstall httpd service] *********************************************** 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=2    changed=1    unreachable=0    failed=0   
192.168.100.132            : ok=2    changed=1    unreachable=0    failed=0   
 
[root@node1 ansible] # ansible testservers -m shell -a 'rpm -q httpd'
192.168.100.131 | FAILED | rc=1 >>
package httpd is not installed
 
192.168.100.132 | FAILED | rc=1 >>
package httpd is not installed
 
[root@node1 ansible] #

保存结果

几乎所有的模块都是会outputs一些东西,甚至debug模块也会.大多数我们会使用的结果变量是changed.这个changed变量决定 了是否要直接handlers和输出的颜色是什么.然而,结果变量还有其他的用途,譬如我需要保存我的结果变量,然后在我们的playbook的其他地方使用.

示例:

分别在一台主机上创建一个目录,另外主机不存在此目录,根据此目录的存在情况,做出不同操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[root@node1 ansible] # ansible testservers -m shell -a 'ls -l /nono'
192.168.100.131 | success | rc=0 >>
total 0
 
192.168.100.132 | FAILED | rc=2 >>
ls : cannot access  /nono : No such  file  or directory
 
[root@node1 ansible] # cat re.yml 
- hosts: testservers
   remote_user: root
   tasks:
    - name:  ls  /nono
      shell:  /bin/ls  /nono
      register: result
      ignore_errors: True
    - name:  test  result
      copy: content= "ok"  dest= /tmp/test
      when: result.rc == 0
    - name:  test  no result
      copy: content= "no ok"  dest= /tmp/test
      when: result.rc != 0
      
[root@node1 ansible] # ansible-playbook re.yml 
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [ ls  /nono ] ************************************************************** 
changed: [192.168.100.131]
failed: [192.168.100.132] => { "changed" true "cmd" "/bin/ls /nono" "delta" "0:00:00.004437" "end" "2016-03-02 12:56:55.409736" "rc" : 2,  "start" "2016-03-02 12:56:55.405299" "warnings" : []}
stderr:  /bin/ls : cannot access  /nono : No such  file  or directory
...ignoring
 
TASK: [ test  result] *********************************************************** 
skipping: [192.168.100.132]
ok: [192.168.100.131]
 
TASK: [ test  no result] ******************************************************** 
skipping: [192.168.100.131]
ok: [192.168.100.132]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=3    changed=1    unreachable=0    failed=0   
192.168.100.132            : ok=3    changed=1    unreachable=0    failed=0   
 
[root@node1 ansible] # ansible testservers -m shell -a 'ls -l /tmp/test'
192.168.100.131 | success | rc=0 >>
-rw-r--r-- 1 root root 2 Mar  2 12:55  /tmp/test
 
192.168.100.132 | success | rc=0 >>
-rw-r--r-- 1 root root 5 Mar  2 12:55  /tmp/test
 
[root@node1 ansible] # ansible testservers -m shell -a 'cat /tmp/test'
192.168.100.131 | success | rc=0 >>
ok
 
192.168.100.132 | success | rc=0 >>
no ok
 
[root@node1 ansible] #

ansible 中的循环操作:

当有需要重复性执行的任务时,可以使用迭代机制,格式为:将需要迭代的内容定义为Item变量引用,并通过with_items 语句来指明迭代的元素列表即可

示例1、

在 testservers 组中一台主机上安装lamp

1
2
3
4
5
6
7
8
9
10
11
12
[root@node1 ansible] # cat item.yml 
- hosts: testservers
   remote_user: root
   tasks:
    - name: yum  install  lamp
      yum: name=`item` state=present
      with_items:
          - httpd
          - mysql-server
          - php
      when: (ansible_nodename ==  "v2.lansgg.com" )
[root@node1 ansible] #

上面的语句等同于:

1
2
3
4
5
6
7
8
9
10
11
12
- hosts: testservers
   remote_user: root
   tasks:
   - name:  install  httpd
     yum: name=httpd state=present
     when: (ansible_nodename ==  "v2.lansgg.com" )
   - name:  install  mysql-server
     yum: name=mysql-server state=present
     when: (ansible_nodename ==  "v2.lansgg.com" )
   - name:  install  php
     yum: name=php state=present
     when: (ansible_nodename ==  "v2.lansgg.com" )

上面的语句 hash 方式编写也可以,等同于如下:

1
2
3
4
5
6
7
8
9
10
- hosts: testservers
   remote_user: root
   tasks:
    - name:  install  httpd
      yum: name=`item`.`name` state=`item`.`state`
      when: (ansible_nodename ==  "v2.lansgg.com" )
      with_items:
       - {name:  'httpd' , state:  'present' }
       - {name:  'mysql-server' , state:  'present' }
       - {name:  'php' , state:  'present' }

开始执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@node1 ansible] # ansible-playbook item.yml 
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [yum  install  lamp] ****************************************************** 
skipping: [192.168.100.132]
changed: [192.168.100.131] => (item=httpd,mysql-server,php)
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=2    changed=1    unreachable=0    failed=0   
192.168.100.132            : ok=1    changed=0    unreachable=0    failed=0

ansible 的 tags 功能

ansible的playbool中有一个关键字,叫做tags。tags是什么?就是打标签。tags可以和一个play(就是很多个task)或者一 个task进行捆绑。然后,ansible-playbook提供了“--skip-tags”和“--tags” 来指明是跳过特定的tags还是执行特定的tags。

示例 1、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@node1 ansible] # cat tag.yml
- hosts: testservers
   remote_user: root
   tasks:
    - name:  echo  A1
      command echo  A1
      tags:
       - A1
    - name:  echo  A2
      command echo  A2
      tags:
       - A2
    - name:  echo  A3
      command echo  A3
      tags:
       - A3

当执行  ansible-playbook tag.yml --tags="A1,A3  ,则只会执行A1和A3的echo命令。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@node1 ansible] # ansible-playbook tag.yml --tags="A1,A3"
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [ echo  A1] *************************************************************** 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
TASK: [ echo  A3] *************************************************************** 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=3    changed=2    unreachable=0    failed=0   
192.168.100.132            : ok=3    changed=2    unreachable=0    failed=0

当执行  ansible-playbook tag.yml --skip-tags="A2" ,同样只会执行 A1和A3的echo命令。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@node1 ansible] # ansible-playbook tag.yml --skip-tags="A2"
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [ echo  A1] *************************************************************** 
changed: [192.168.100.132]
changed: [192.168.100.131]
 
TASK: [ echo  A3] *************************************************************** 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=3    changed=2    unreachable=0    failed=0   
192.168.100.132            : ok=3    changed=2    unreachable=0    failed=0

示例 2 、

我们安装 httpd 服务的流程为 安装服务、copy文件、启动服务、如果配置有变化就重启服务,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@node1 ansible] # cat http.yml 
- hosts: testservers
   remote_user: root
   tasks:
   - name:  install  httpd package
     yum: name=httpd state=present
   - name: start httpd service
     service: name=httpd enabled= true  state=started
   - name: copy config  file
     copy: src=httpd.conf dest= /etc/httpd/conf/httpd .conf
     notify:
        restart httpd service
     tags:
      - modify
   handlers:
    - name: restart httpd service
      service: name=httpd state=restarted
[root@node1 ansible] #

当我们的配置文件有修改的时候,可以指定tags,这样就会只执行copy config file 任务,前面就不会再执行

结果如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@node1 ansible] # ansible-playbook http.yml --tags=modify
 
PLAY [testservers] ************************************************************ 
 
GATHERING FACTS *************************************************************** 
ok: [192.168.100.131]
ok: [192.168.100.132]
 
TASK: [copy config  file ] ****************************************************** 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
NOTIFIED: [restart httpd service] ********************************************* 
changed: [192.168.100.131]
changed: [192.168.100.132]
 
PLAY RECAP ******************************************************************** 
192.168.100.131            : ok=3    changed=2    unreachable=0    failed=0   
192.168.100.132            : ok=3    changed=2    unreachable=0    failed=0

特殊 tags

系统中内置的特殊tags:

  always、tagged、untagged、all 是四个系统内置的tag,有自己的特殊意义

  always: 指定这个tag 后,task任务将永远被执行,而不用去考虑是否使用了--skip-tags标记

  tagged: 当 --tags 指定为它时,则只要有tags标记的task都将被执行,--skip-tags效果相反

  untagged: 当 --tags 指定为它时,则所有没有tag标记的task 将被执行,--skip-tags效果相反

  all: 这个标记无需指定,ansible-playbook 默认执行的时候就是这个标记.所有task都被执行


本文转自 西索oO 51CTO博客,原文链接:http://blog.51cto.com/lansgg/1746825


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
Shell
shell学习(六) 【case多条件分支语句】
shell学习(六) 【case多条件分支语句】
11 1
|
9月前
|
Shell 项目管理
ansible之when条件语法、处理任务失败、jinja2模板和项目管理
ansible之when条件语法、处理任务失败、jinja2模板和项目管理
72 0
|
7月前
|
JSON 程序员 数据格式
优雅地处理Python中的条件分支:字典映射、函数组合与match-case语句
在本文中,我们探讨了如何在Python中优雅地处理条件分支,以避免使用过多的if语句。文章介绍了两种解决方案:字典映射与函数组合以及Python 3.10中引入的match-case语句。这些方法使得代码结构更加清晰、简洁且易于维护和扩展。
82 0
|
Shell
Shell条件测试符及if条件语句
Shell条件测试符及if条件语句
120 0
|
Java Shell 程序员
shel脚本基础系列(三)for-while循环
shel脚本基础系列(三)for-while循环
181 0
shel脚本基础系列(三)for-while循环
|
Shell
shell for if 循环中判断条件来执行命令
备份所有 .pid 的文件为 .pid.backup
1057 0
|
应用服务中间件 nginx Python
Ansible-playbook loops循环with_items(学习笔记二十一)
文件 [root@ansible-server ansible]# tree ./ ./ ├── hosts └── loops.yaml hosts 文件 [web] 192.
1259 0
|
Linux 开发工具 Python
Ansible-playbook 条件判断when、pause(学习笔记二十三)
有一些模块,例如copy这个模块有一些机制能跳过本次模块的运行.其实我们也可以使用自己的条件语句去配置跳过模块,这样方便你服务能够选择使用不同的包管理(apt,yum)和不同的文件系统.
1604 0