事实、循环、条件判断

事实、循环、条件判断

1.描述Ansible事实

​ Ansible事实是Ansible在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。

​ 为受管主机收集的一些事实可能包括:

  • 主机名称
  • 内核版本
  • 网络接口
  • IP地址
  • 操作系统版本
  • 各种环境变量
  • CPU数量
  • 提供的或可用的内存
  • 可用磁盘空间

借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。例如:

  • 可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
  • 可以根据通过事实报告的可用内存来自定义MySQL配置文件
  • 可以根据事实的值设置配置文件中使用的IPv4地址

通常,每个play在执行第一个任务之前会先自动运行setup模块来收集事实。

​ 查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug模块显示ansible_facts变量值的简短playbook。

我们用模块获取对面的事实。

[root@node1 ansible]# ansible 192.168.100.147 -m setup
192.168.100.147 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.100.147"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::79b2:48d0:db63:ff3e"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "07/22/2020",
        "ansible_bios_version": "6.00",
        "ansible_cmdline": {
            "BOOT_IMAGE": "(hd0,msdos1)/vmlinuz-4.18.0-257.el8.x86_64",
此内容省略。。。。。。

我们直接获取对面全部内容,内容可能很多, 这个时候我们可以只查看前面的内容

[root@node1 ansible]# ansible 192.168.100.147 -m setup|less

我们用playbook获取对面的事实

[root@node1 ansible]# cat test.yml    //如果需要获取对面全是的事实playbook入下
---
- hosts: 192.168.100.147
  tasks: 
    - name: ansible_facts
      debug: 
        var: ansible_facts

[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook test1/test.yml 

PLAY [192.168.100.147] *********************************************************************************************

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

TASK [print all facts] *********************************************************************************************
ok: [192.168.100.147] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.100.147"
        ],
        "all_ipv6_addresses": [
            "fe80::79b2:48d0:db63:ff3e"
        ],
        "ansible_local": {},
此处内容省略。。。。。。

我们也可以获取指定的事实内容,比如我们获取对面的IP地址

[root@node1 ansible]# cat test1/test.yml    //playbook内容写法
---
- hosts: '192.168.100.147'
  tasks: 
    - name: print all facts
      debug: 
        var: ansible_facts['default_ipv4']['address']

[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook test1/test.yml   //公告获取到对面的IP

PLAY [192.168.100.147] *********************************************************************************************

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

TASK [print all facts] *********************************************************************************************
ok: [192.168.100.147] => {
    "ansible_facts['default_ipv4']['address']": "192.168.100.147"
}

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

[root@node1 ansible]# 

获取指定内容,还有简便的写法

[root@node1 ansible]# cat test1/test.yml   
---
- hosts: '192.168.100.147'
  tasks: 
    - name: print all facts
      debug: 
        var: ansible_facts.default_ipv4.address  //这里我们用点代表,

[root@node1 ansible]# 

Playbook以JSON格式显示ansible_facts变量的内容。

下表显示了可能从受管节点收集的并可在playbook中使用的一些事实:

事实变量
短主机名ansible_facts[‘hostname’]
完全限定域名ansible_facts[‘fqdn’]
IPv4地址ansible_facts[‘default_ipv4’][‘address’]
所有网络接口的名称列表ansible_facts[‘interfaces’]
/dev/vda1磁盘分区的大小ansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’]
DNS服务器列表ansible_facts[‘dns’][‘nameservers’]
当前运行的内核版本ansible_facts[‘kernel’]

如果变量的值为散列/字典类型,则可使用两种语法来获取其值。比如:

  • ansible_facts[‘default_ipv4’][‘address’]也可以写成ansible_facts.default_ipv4.address
  • ansible_facts[‘dns’][‘nameservers’]也可以写成ansible_facts.dns.nameservers //这种方法虽然简便,但是不推荐使用,因为可能会和python中的某些函数会冲突,所以不建议使用。

注:msg能在之前的变量上面去加东西

在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:

[root@node1 ansible]# cat test1/test.yml 
---
- hosts: '192.168.100.147'
  tasks: 
    - name: test
      debug: 
        msg: >   //在这里的意思是打印一行的内容出来,为了美观所以我们可以换行写
          The host named  {{ ansible_facts['fqdn'] }} of ip is
          {{ ansible_facts['default_ipv4']['address'] }}

[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook test1/test.yml 

PLAY [192.168.100.147] *********************************************************************************************

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

TASK [test] ********************************************************************************************************
ok: [192.168.100.147] => {
    "msg": "The host named  node2 of ip is 192.168.100.147\n"     //ip已经出来了
}

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

2.ansible事实作为变量注入

​ 在Ansible2.5之前,事实是作为前缀为字符串ansible_的单个变量注入,而不是作为ansible_facts变量的一部分注入。例如,ansible_facts[‘distribution’]事实会被称为ansible_distribution。

​ 许多较旧的playbook仍然使用作为变量注入的事实,而不是在ansible_facts变量下创建命名空间的新语法。我们可以使用临时命令来运行setup模块,以此形式显示所有事实的值。以下示例中使用一个临时命令在受管主机192.168.100.147上运行setup模块:

ansible 172.16.103.129 -m setup   //这也就是我们上面第一条获取对面事实的命令

ansible事实名称比较

ansible_facts形式旧事实变量形式
ansible_facts[‘hostname’]ansible_hostname
ansible_facts[‘fqdn’]ansible_fqdn
ansible_facts[‘default_ipv4’][‘address’]ansible_default_ipv4[‘address’]
ansible_facts[‘interfaces’]ansible_interfaces
ansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’]ansible_devices[‘vda’][‘partitions’][‘vda1’][‘size’]
ansible_facts[‘dns’][‘nameservers’]ansible_dns[‘nameservers’]
ansible_facts[‘kernel’]ansible_kernel

​ 目前,Ansible同时识别新的事实命名系统(使用ansible_facts)和旧的2.5前“作为单独变量注入的事实”命名系统。

​ 将Ansible配置文件的**[default]部分中inject_facts_as_vars参数设置为False**,可关闭旧命名系统。默认设置目前为True

[root@node1 ansible]# vim ansible.cfg //进入配置文件


# inject_facts_as_vars = True    //改为false就可以执行旧命令了,记得取消注释

inject_facts_as_vars的默认值在Ansible的未来版本中可能会更改为False。如果设置为False,则只能使用新的**ansible_facts.***命名系统引用Ansible事实。所以建议大家一开始就要适应这种方式。

3.关闭事实收集

有时我们不想为play收集事实。这样做的原因可能有:

  • 不准备使用任何事实
  • 希望加快play速度
  • 希望减小play在受管主机上造成的负载
  • 受管主机因为某种原因无法运行setup模块
  • 需要安装一些必备软件后再收集事实

以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:

[root@node1 ansible]# cat test1/test.yml 
---
- hosts: '192.168.100.147'
  gather_facts: no     //如果我们不想获取对面的事实, 那么我们就要关闭掉。
  tasks: 
    - name: test
      debug: 
        msg: >
          The host named  {{ ansible_facts['fqdn'] }} of ip is
          {{ ansible_facts['default_ipv4']['address'] }}

[root@node1 ansible]# 

即使play设置了gather_facts: no,也可以随时通过运行使用setup模块的任务来手动收集事实:

[root@node1 ansible]# cat test1/test.yml 
---
- hosts: '192.168.100.147'
  gather_facts: no 
  tasks: 
    - name: test
      setup: 
    - name: debug
      debug: 
        var: ansible_facts


[root@node1 ansible]# 

4.创建自定义事实

​ 除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到setup模块在受管主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整play的行为。

​ 自定义事实可以在静态文件中定义,格式可为INI文件或采用JSON。它们也可以是生成JSON输出的可执行脚本,如同动态清单脚本一样。

​ 有了自定义事实,我们可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。

​ 默认情况下,setup模块从各受管主机的**/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact**结尾才能被使用。动态自定义事实脚本必须输出JSON格式的事实,而且必须是可执行文件。

​ 以下是采用INI格式编写的静态自定义事实文件。INI格式的自定义事实文件包含由一个部分定义的顶层值,后跟用于待定义的事实的键值对:

[packages]     //这个配置文件要在受管主机上写入
web_package = httpd
db_package = mariadb-server

[users]
user1 = joe
user2 = jane

​ 同样的事实可能以JSON格式提供。以下JSON事实等同于以上示例中INI格式指定的事实。JSON数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出:

{
  "packages": {
    "web_package": "httpd",
    "db_package": "mariadb-server"
  },
  "users": {
    "user1": "joe",
    "user2": "jane"
  }
}

注意:

自定义事实文件不能采用playbook那样的YAML格式。JSON格式是最为接近的等效格式。

自定义事实由setup模块存储在ansible_facts.ansible_local变量中。

事实按照定义它们的文件的名称来整理。例如,假设前面的自定义事实由受管主机上保存为**/etc/ansible/facts.d/custom.fact**的文件生成。在这种情况下,

ansible_facts.ansible_local[‘custom’][‘users’][‘user1’]的值为joe

可以利用临时命令在受管主机上运行setup模块来检查自定义事实的结构。

[root@node1 ansible]# ansible 192.168.100.147 -m setup|less  //执行之后我们在下面搜索local和packages,我们发现有这两个东西,也就是我们刚刚上面再受管主机写的东西。

        "ansible_local": {
            "custom": {
                "packages": {
                    "db_package": "mariadb-server",
                    "web_package": "httpd"


                "packages": {
                    "db_package": "mariadb-server",
                    "web_package": "httpd"

注意:自定义事实的使用方式与playbook中的默认事实相同:

---
- hosts: all
  tasks:
  - name: Prints various Ansible facts
    debug:
      msg: >
        The package to install on {{ ansible_facts['fqdn'] }}
        is {{ ansible_facts['ansible_local']['cutstom']['packages']['web_package'] }}

5.魔法变量

一些变量并非事实或通过setup模块配置,但也由Ansible自动设置。这些魔法变量也可用于获取与特定受管主机相关的信息。

最常用的有四个:

魔法变量说明
hostvars包含受管主机的变量,可以用于获取另一台受管主机的变量的值。 如果还没有为受管主机收集事实,则它不会包含该主机的事实。
group_names列出当前受管主机所属的所有组
groups列出清单中的所有组和主机
inventory_hostname包含清单中配置的当前受管主机的主机名称。 因为各种原因有可能与事实报告的主机名称不同

​ 另外还有许多其他的“魔法变量”。有关更多信息,请参见以下链接:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable。

若要深入了解它们的值,一个途径是使用debug模块报告特定主机的hostvars变量的内容:

ansible 172.16.103.129 -m debug -a 'var=hostvars["localhost"]'

6.利用循环迭代任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。

请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态:

- name: Postfix is running
  service:
    name: postfix
    state: started
    
- name: Devecot is running
  service:
    name: dovecot
    state: started        //利用两次来确保这个服务启动,显得多此一举,我们可以用更简洁的方法

这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行:

- name: service
  service:
    name: "{{ item }}"
    state: started
  loop:
    - postfix
    - dovecot

例子:

如果我们想创建多个用户,比如十个,百个,我们可以利用循环来创建,代码如下:

[root@node1 ansible]# cat test1/test.yml    //这里比如我们创建五个用户shen
---
- hosts: 192.168.100.147
  tasks: 
    - name: create user
      user: 
        name: '{{item}}'
        state: present
      loop: 
        - shen1
        - shen2
        - shen3
        - shen4
        - shen5
[root@node1 ansible]# 

 
[root@node1 ansible]# ansible-playbook test1/test.yml    //下面可以看见,我们创建成功,此时受管主机应该是由我们五个用户的

PLAY [192.168.100.147] *******************************************************************************************

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

TASK [create user] ***********************************************************************************************
changed: [192.168.100.147] => (item=shen1)
changed: [192.168.100.147] => (item=shen2)
changed: [192.168.100.147] => (item=shen3)
changed: [192.168.100.147] => (item=shen4)
changed: [192.168.100.147] => (item=shen5)

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

[root@node1 ansible]# 

[root@node2 ~]# id shen1     //受管主机有这五个用户
uid=1002(shen1) gid=1002(shen1) 组=1002(shen1)
[root@node2 ~]# id shen2
uid=1003(shen2) gid=1003(shen2) 组=1003(shen2)
[root@node2 ~]# id shen3
uid=1004(shen3) gid=1004(shen3) 组=1004(shen3)
[root@node2 ~]# id shen4
uid=1005(shen4) gid=1005(shen4) 组=1005(shen4)
[root@node2 ~]# id shen5
uid=1006(shen5) gid=1006(shen5) 组=1006(shen5)
[root@node2 ~]# 

​ 可以通过一个变量提供loop所使用的列表。在以下示例中,变量mail_services含有需要处于运行状态的服务的列表。

用变量来做

[root@node1 node]# cat llll.yml     //创建一个文件,写上这些内容
users: 
  - shen6
  - shen7
  - shen8
  - shen9
  - shen10
[root@node1 node]# 


[root@node1 ansible]# cat test.yml    //如果我们利用变量, 那我们就这样写
---
- hosts: 192.168.100.147
  vars_files: 
    node/llll.yml
  tasks: 
    - name: create user
      user: 
        name: '{{item}}'
        state: present
      loop: '{{users}}'
[root@node1 ansible]#


[root@node1 ansible]# ansible-playbook test.yml    //执行成功

PLAY [192.168.100.147] *********************************************************************************************

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

TASK [create user] *************************************************************************************************
changed: [192.168.100.147] => (item=shen6)
changed: [192.168.100.147] => (item=shen7)
changed: [192.168.100.147] => (item=shen8)
changed: [192.168.100.147] => (item=shen9)
changed: [192.168.100.147] => (item=shen10)

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

7.循环散列或字典列表

loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即namegroups,当前item循环变量中每个键的值可以分别通过item.nameitem.groups变量来检索。

[root@node1 node]# vim llll.yml      //现在我们来换一种写法
[root@node1 node]# cat llll.yml 
users: 
  - name: shen1
    uid: 2000
  - name: shen2
    uid: 3000
  - name: shen3
    uid: 4000
  - name: shen4
    uid: 5000
[root@node1 node]# 


[root@node1 ansible]# cat test.yml    //注意执行文件的写法
---
- hosts: 192.168.100.147
  vars_files: 
    node/llll.yml
  tasks: 
    - name: create user
      user: 
        name: '{{item.name}}'   //
        uid: '{{item.uid}}'
        state: present
      loop: '{{users}}'
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook test.yml     //执行成功

PLAY [192.168.100.147] *********************************************************************************************

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

TASK [create user] *************************************************************************************************
changed: [192.168.100.147] => (item={'name': 'shen1', 'uid': 2000})
changed: [192.168.100.147] => (item={'name': 'shen2', 'uid': 3000})
changed: [192.168.100.147] => (item={'name': 'shen3', 'uid': 4000})
changed: [192.168.100.147] => (item={'name': 'shen4', 'uid': 5000})

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

[root@node1 ansible]# 


[root@node2 ~]# id shen1       //可以看见他的uid已经改变了
uid=2000(shen1) gid=1002(shen1) 组=1002(shen1)
[root@node2 ~]# id shen2
uid=3000(shen2) gid=1003(shen2) 组=1003(shen2)
[root@node2 ~]# id shen3
uid=4000(shen3) gid=1004(shen3) 组=1004(shen3)
[root@node2 ~]# id shen4
uid=5000(shen4) gid=1005(shen4) 组=1005(shen4)
[root@node2 ~]# 

8.较早样式的循环关键字

​ 在Ansible2.5之前,大多数playbook使用不同的循环语法。提供了多个循环关键字,前缀为whth_,后面跟Ansible查找插件的名称。这种循环语法在现有playbook中很常见,但在将来的某个时候可能会被弃用。

较早样式的Ansible循环

循环关键字描述
with_items行为与简单列表的loop关键字相同,例如字符串列表或散列/字典列表。 但与loop不同的是,如果为with_items提供了列表的列表, 它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。
with_file此关键字需要控制节点文件名列表。循环变量item在每次迭代过程中保存文件列表中相应文件的内容。
with_sequence此关键字不需要列表,而是需要参数来根据数字序列生成值列表。 循环变量item在每次迭代过程中保存生成的序列中的一个生成项的值。

playbook中的with_items的示例如下所示:

vars:
  data:
    - user0
    - user1
    - user2
tasks:
  - name: "with_items"
    debug:
      msg: "{{ item }}"
    with_items: "{{ data }}"

从Ansible2.5开始,建议使用loop关键字编写循环。

9.将register变量与loop一起使用

​ register关键字也可以捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:

[root@node1 ansible]# cat test.yml 
---
- hosts: 192.168.100.147
  tasks: 
    - name: test
      command: "echo shunzi {{item}},ni xi huan chi shi"  
      loop:
        - shen1
        - shen2
        - shen3
      register: result
    - debug: 
        var: result

[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook test.yml      //执行成功,我们可以发现他给我指定的用户打招呼的内容

PLAY [192.168.100.147] *******************************************************************************************

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

TASK [test] ******************************************************************************************************
changed: [192.168.100.147] => (item=shen1)
changed: [192.168.100.147] => (item=shen2)
changed: [192.168.100.147] => (item=shen3)

TASK [debug] *****************************************************************************************************
ok: [192.168.100.147] => {
    "result": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": [
                    "echo",
                    "shunzi",
                    "shen1,ni",
                    "xi",
                    "huan",
                    "chi",
                    "shi"
                ],
                "delta": "0:00:00.006161",
                "end": "2021-07-25 07:09:28.296358",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo shunzi shen1,ni xi huan chi shi",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "shen1",
                "rc": 0,
                "start": "2021-07-25 07:09:28.290197",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "shunzi shen1,ni xi huan chi shi",
                "stdout_lines": [
                    "shunzi shen1,ni xi huan chi shi"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": [
                    "echo",
                    "shunzi",
                    "shen2,ni",
                    "xi",
                    "huan",
                    "chi",
                    "shi"
                ],
                "delta": "0:00:00.002744",
                "end": "2021-07-25 07:09:28.647163",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo shunzi shen2,ni xi huan chi shi",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "shen2",
                "rc": 0,
                "start": "2021-07-25 07:09:28.644419",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "shunzi shen2,ni xi huan chi shi",
                "stdout_lines": [
                    "shunzi shen2,ni xi huan chi shi"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": [
                    "echo",
                    "shunzi",
                    "shen3,ni",
                    "xi",
                    "huan",
                    "chi",
                    "shi"
                ],
                "delta": "0:00:00.003040",
                "end": "2021-07-25 07:09:28.977042",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo shunzi shen3,ni xi huan chi shi",
                        "_uses_shell": false,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "shen3",
                "rc": 0,
                "start": "2021-07-25 07:09:28.974002",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "shunzi shen3,ni xi huan chi shi",
                "stdout_lines": [
                    "shunzi shen3,ni xi huan chi shi"
                ]
            }
        ]
    }
}

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

[root@node1 ansible]# 

在上面的例子中,results键包含一个列表。在下面,修改了playbook,使第二个任务迭代此列表:

[root@node1 ansible]# cat test.yml 
---
- hosts: 192.168.100.147
  tasks: 
    - name: test
      command: "echo shunzi {{item}},ni xi huan chi shi"  
      loop:
        - shen1
        - shen2
        - shen3
      register: result
    - debug: 
        msg: "STDOUT from previous task: {{ item.stdout }}"
      loop: "{{ echo_results['results'] }}"

[root@node1 ansible]# 

10.有条件的运行任务

Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。

我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。

==
<
>
<=
>=

以下场景说明了在Ansible中使用条件的情况

  • 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
  • Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理。
  • 可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)。
  • 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
  • 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改。

when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。

可以测试的一个最简单条件是某一布尔变量是True还是False。以下示例中的when语句导致任务仅在run_my_taskTrue时运行:

[root@node1 ansible]# cat test.yml 
---
- name: test
  hosts: 192.168.100.147
  vars_files:
    node/llll.yml
  vars: 
    power: true        //给一个判断   
  tasks: 
    - name: create user
      user:
        name: "{{ item.name}}"
        uid: "{{item.uid}}"
        state: absent
      loop: "{{users}}"
      when: power
[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook test.yml    //执行成功

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

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

TASK [create user] ***********************************************************************************************
changed: [192.168.100.147] => (item={'name': 'shen1', 'uid': 2000})
changed: [192.168.100.147] => (item={'name': 'shen2', 'uid': 3000})
changed: [192.168.100.147] => (item={'name': 'shen3', 'uid': 4000})
changed: [192.168.100.147] => (item={'name': 'shen4', 'uid': 5000})

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

​ 以下示例测试my_service变量是否具有值。若有值,则将my_service的值用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。

[root@node1 ansible]# cat test.yml 
---
- name: test
  hosts: 192.168.100.147
  vars_files:
    node/llll.yml      
  tasks: 
    - name: create user
      user:
        name: "{{ item.name}}"
        uid: "{{item.uid}}"
        state: present
      loop: "{{users}}"
      when: '"{{ item.name }}" == "{{ shen3}}"'
[root@node1 ansible]# 

下表显示了在处理条件时可使用的一些运算:

操作示例
等于(值为字符串)ansible_machine == “x86_64”
等于(值为数字)max_memory == 512
小于min_memory < 128
大于min_memory > 256
小于等于min_memory <= 256
大于等于min_memory >= 512
不等于min_memory != 512
变量存在min_memory is defined
变量不存在min_memory is not defined
布尔变量是True。1、True或yes的求值为Truememory_available
布尔变量是False。0、False或no的求值为Falsenot memory_available
第一个变量的值存在,作为第二个变量的列表中的值ansible_distribution in supported_distros
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,让我来回答你的问题。 首先,你可以编写一个 Ansible playbook 来启动或停止多个 SysV 服务。你可以使用 `service` 模块来实现这一点。以下是一个基本的 playbook: ``` - name: Manage SysV services hosts: node2:node3 gather_facts: false tasks: - name: Start services service: name: "{{ item }}" state: started loop: - service1 - service2 - service3 when: inventory_hostname == 'node2' - name: Stop services service: name: "{{ item }}" state: stopped loop: - service1 - service2 - service3 when: inventory_hostname == 'node3' ``` 在这个 playbook 中,我们定义了两个任务:一个任务用来启动服务,另一个任务用来停止服务。我们使用了 `loop` 来遍历服务列表,并使用 `when` 条件判断来确定在哪些主机上运行这些任务。 此外,我们还使用了 `gather_facts: false` 来禁用 Ansible 的事实收集功能。这是因为我们已经知道了我们要管理的节点,所以不需要额外的信息。 最后,如果你还想在节点上安装服务,可以使用 `yum` 或 `apt` 模块来安装剩余的服务。你可以使用 `with_items` 循环来安装多个服务。以下是一个示例: ``` - name: Install additional services hosts: node2:node3 gather_facts: false tasks: - name: Install services yum: name: "{{ item }}" state: present with_items: - service4 - service5 when: inventory_hostname == 'node2' ``` 在这个 playbook 中,我们使用 `yum` 模块安装了两个服务。我们使用了 `with_items` 循环来遍历服务列表,并使用 `when` 条件判断来确定在哪些主机上运行这些任务。 希望这可以回答你的问题。如果你有任何其他问题,请随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lfei5120

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值