ansible的详细讲解

一:Ansible介绍

1.Ansible是什么

Ansible是一个开源的IT自动化配置部署,管理的工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

2.Ansible配置文件优先级

● 用户可以修改一下配置文件来修改设置,他们的被读取的顺序如下:

* ANSIBLE_CONFIG (一个环境变量)
* ansible.cfg (位于当前目录中)
* .ansible.cfg (位于家目录中)
* /etc/ansible/ansible.cfg

● 版本1.5之前的读取顺序如下:

* ansible.cfg (位于当前目录)
* ANSIBLE_CONFIG (一个环境变量)
* .ansible.cfg (位于家目录下)
* /etc/ansible/ansible.cfg

Ansible 将会按以上顺序逐个查询这些文件,直到找到一个为止,并且使用第一个寻找到个配置文件的配置,这些配置将不会被叠加.

3.Ansible的特性和优点

(1).Ansible的特性

①.no agent: 不需要在被管控主机上安装任何软件,
②.no server: 无服务器端,使用时直接运行命令即可,
③.modules in any languages:基于模块工作,可使用任意语言开发模块,
④.yaml,not code:使用yaml语言定制剧本playbook,
⑤.ssh by default:基于SSH工作
⑥.strong multi-tier solution:可实现多级指挥

(2).ansible的优点

①.轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
②.批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
③.使用python编写,维护更简单,ruby语法过于复杂;
④.支持sudo。

ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务

二、Ansible的安装

1.离线安装

. https://editor.csdn.net/md/?articleId=122209342
 ②. https://download.csdn.net/download/weixin_46031767/72084482
    https://download.csdn.net/download/weixin_46031767/72086885 
    自带README

2.在线安装

 yum install -y epel-release
 yum install -y ansible
 [root@an1 ~]# ansible --version
  ansible 2.9.25
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

三、Ansiible的基本用法

1.linux端口、免密的配置(Inventory参数说明)

通过设置下面的参数,可以控制 ansible 与远程主机的交互方式
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

 ;ansible_ssh_user  #默认的 ssh 用户名
 ;ansible_ssh_pass  #ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

  ansible_ssh_port   #ssh端口号.如果不是默认的端口号,通过此变量设置.
  ansible_sudo_pass  #指明sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

以变量的形式添加

[test]
192.168.137.107

[test:vars]
ansible_ssh_user=root
ansible_ssh_pass='123'

加在ip后面

[test]
192.168.137.107 ansible_ssh_user=root ansible_ssh_pass='123'

2.Ansible的语法参数

ansible命令语法介绍 ansible HOST-PATTERN [-f FORKS] [-M MOD_NAME] [-a MOD_ARGS]
-f FORKS:表示一批处理几台主机,也就是当被管控主机很多时,ansible不是对所有主机同时发起管理操作,而是一批处理几台,然后再换一批,直到所有主机被处理完成,如果不指定,则默认是5台
-m MOD_NAME:指明调用哪个模块执行操作,各个模块所能实现的功能不同,如果不指定,默认是用-m command模块
-a MOD_ARGS:指明使用该模块的执行操作时的参数

    [root@master ~]# ansible-doc -l获取支持的模块 注意每个模块的用法可以使用 ansible-doc MOD 
如: [root@master ~]# ansible-doc copy
- name: Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version
  copy:
    src: /mine/ntp.conf
    dest: /etc/ntp.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes

modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.

3.Ansible远程执行命令测试连通性

ping模块:用来检测网络的连通性

[root@an1 first]# ansible -i inventory test -m ping 
192.168.137.107 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

四、Ansible模块

1.shell模块

使用shell模块的时候默认是通过/bin/sh来执行的,所以在终端输入的各种命令都可以使用
在远程主机执行命令,相当于调用远程主机的shell进程,然后在该shell下打开一个子shell运行命令。支持shell特性,如管道,重定向等

[root@an1 first]# ansible -i inventory test -m shell -a 'free -h'
192.168.137.107 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3.8G        238M        3.4G         11M        200M        3.4G
Swap:          2.0G          0B        2.0G

常见参数有:

  • chdir= 表示指明命令在远程主机上哪个目录下运行
  • creates= 如果文件已存在,则不会执行任务命令(可用于判断)
  • removes= 如果文件存在,则会执行任务命令
  • executeble= 指明运行命令的shell程序

2.command模块

在远程主机执行命令,不支持管道,重定向等shell特性

[root@an1 first]# ansible -i inventory test -m command -a 'date'
192.168.137.107 | CHANGED | rc=0 >>
Thu Jan  6 17:27:59 CST 2022

常用参数:

  • chdir= 表示指明命令在远程主机上哪个目录下运行,也就是在命令执行前切换到哪个目录下
  • creates= 一个文件名,如果文件已存在,则不会执行任务
  • removes= 如果文件不存在,则不会执行命令任务
  • executeble= 指明运行命令的shell程序
[root@an1 first]# ansible test2 -m command -a 'chdir=/home ls'
192.168.137.107 | CHANGED | rc=0 >>
mysql
test12

3.script模块

将管理端的某个脚本,移动到远端主机(不需要指明传递到远端主机的哪个路径下,系统会自动移动,然后执行),一般是自动移动到远端主机的/root/.ansible/tmp目录下,然后自动给予其权限,然后再开个子shell然后运行脚本,运行完成后删除脚本

[root@awx linux]# ansible -i inventory linux -m script -a '/root/ansible/linux/test.sh'
192.168.6.44 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 192.168.6.44 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 192.168.6.44 closed."
    ],
    "stdout": "",
    "stdout_lines": []
}

playbook
注意: cript模块后面是不需要用sh指令的了,如下面这样就是错误的使用方法script: sh /home/wfq/ops/asb/playbook/test_script.sh

##正确写法
- hosts: linux
  gather_facts: false
  tasks:
  - name: script test
    script: "/root/ansible/linux/test.sh"

4.copy模块

拷贝ansible管理端的文件到远程主机的指定位置

常见参数有:

  • src= 指明本地路径下的某个文件,可以使用相对路径和绝对路径,支持直接指定目录,如果源是目录,则目标也要是目录
  • dest= 指明拷贝文件的目标目录位置,使用绝对路径,如果源是目录,则目标也要是目录,如果目标文件已存在,会覆盖原有内容
  • mode= 指明复制时,目标文件的权限
  • owner= 指明复制时,目标文件的属主
  • group= 指明复制时,目标文件的属组
  • content= 指明复制到目标主机上的内容,不能与src一起使用,相当于复制content指明的数据,到目标文件中
  • backup #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
[root@awx linux]# ansible -i inventory linux -m copy -a 'src=/etc/passwd dest=/tmp/ mode=777'
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "b52734ebae056d578d74d38b32d312ad42a9bd96",
    "dest": "/tmp/passwd",
    "gid": 0,
    "group": "root",
    "md5sum": "9f72e7c0aa51b2e4b5cc493887ddfb99",
    "mode": "0777",
    "owner": "root",
    "size": 1045,
    "src": "/root/.ansible/tmp/ansible-tmp-1642061769.8627417-7805-115845615829882/source",
    "state": "file",
    "uid": 0
}
[root@awx linux]# ansible -i inventory linux -m copy -a 'content="hello world" dest=/tmp/test.txt mode=777'
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
    "dest": "/tmp/test.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "5eb63bbbe01eeed093cb22bb8f5acdc3",
    "mode": "0777",
    "owner": "root",
    "size": 11,
    "src": "/root/.ansible/tmp/ansible-tmp-1642062025.57808-8122-94579629553992/source",
    "state": "file",
    "uid": 0
}
[root@awx linux]# cat copy.yml 
- hosts: linux
  gather_facts: false
  tasks:
  - name: copy test
    copy: 
      src: /etc/passwd
      dest: /tmp/passssss
      mode: 777

5.yum模块

基于yum机制,对远程主机管理程序包

常用参数有:

  • name= 指明程序包的名称,可以带上版本号,不指明版本,就是默认最新版本。
  • state=present|latest|absent 指明对程序包执行的操作,present表示安装程序包,latest表示安装最新版本的程序包,absent表示卸载程序包

  • disablerepo= 在用yum安装时,临时禁用某个仓库,仓库的ID
  • enablerepo= 在用yum安装时,临时启用某个仓库,仓库的ID
  • conf_file= 指明yum运行时采用哪个配置文件,而不是使用默认的配置文件
  • diable_gpg_check=yes|no 是否启用gpg-check
[root@awx linux]# ansible -i inventory linux -m yum -a 'name=httpd state=present'
[root@awx linux]# ansible-playbook -i inventory yum.yml 

PLAY [linux] ***********************************************************************************************************************

TASK [yum test] ********************************************************************************************************************
changed: [192.168.6.44]

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

6.service模块

用来管理远程主机上的服务的模块

常见参数有:

  • name= 被管理的服务名称
  • state=started|stopped|restarted 表示启动或关闭或重启
  • enabled=yes|no 表示要不要设定该服务开机自启动
  • runlevel= 如果设定了enabled开机自动启动,则要定义在哪些运行级别下自动启动 2345
[root@awx linux]# ansible -i inventory linux -m service -a 'name=httpd state=started enabled=yes runlevel=2345'

7.file模块

用于设定远程主机上的文件属性

常见参数有:

  • path= 指明对哪个文件修改其属性
  • src= 指明path=指明的文件是软链接文件,其对应的源文件是谁,必须要在state=link时才有用
  • state=touch|directory|link|absent 表示创建的文件是目录还是软链接 touch表示创建文件
    ---- state的选项 touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间 file:即使文件不存在,也不会被创建
    recurse参数:当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性。这仅在state设置为directory时适用。
  • owner= 指明文件的属主
  • group= 指明文件的属组
  • mode= 指明文件的权限

  • 创建软链接的用法:
    src= path= state=link
  • 修改文件属性的用法:
    path= owner= mode= group=
  • 创建目录的用法:
    path= state=directory
  • 删除文件:
    path= state=absent
[root@awx linux]# ansible -i inventory linux -m file -a 'path=/tmp/aaaaaaaaaaaaaa state=touch'
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "dest": "/tmp/aaaaaaaaaaaaaa",
    "gid": 0,
    "group": "root",
    "mode": "0644",
    "owner": "root",
    "size": 0,
    "state": "file",
    "uid": 0
}

8.user模块

管理远程主机上的用户的账号

常见参数有:

  • name= 指明要管理的账号名称
  • state=present|absent 指明是创建账号还是删除账号,present表示创建,absent表示删除
  • system=yes|no 指明是否为系统账号
  • uid= 指明用户UID
  • group= 指明用户的基本组
  • groups= 指明用户的附加组
  • shell= 指明默认的shell
  • home= 指明用户的家目录
  • move_home=yes|no 当home设定了家目录,如果要创建的家目录已存在,是否将已存在的家目录进行移动
  • password= 指明用户的密码,最好使用加密好的字符串
  • comment= 指明用户的注释信息
  • remove=yes|no 当state=absent时,也就是删除用户时,是否要删除用户的而家目录
[root@awx linux]# ansible -i inventory linux -m user -a 'name=macy state=present '
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1002,
    "home": "/home/macy",
    "name": "macy",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1002
}

9.group模块

用来添加或删除远端主机的用户组

常见参数有:

  • name= 被管理的组名
  • state=present|absent 是添加还是删除,不指名默认为添加
  • gid= 指明GID
  • system=yes|no 是否为系统组
[root@awx linux]# ansible -i inventory linux -m group -a 'name=test111 state=present gid=6666'
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "gid": 6666,
    "name": "test111",
    "state": "present",
    "system": false
}

10.template模块

基于模板方式,生成一个模板文件,复制到远程主机,让远程主机基于模板,生成符合远程主机自身的文件
template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。
说明:
1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。
2、模板文件后缀名为.j2。

注意:此模块不能在命令行使用,只能用在playbook中

常见的参数有:

  • src= 指明管理端本地的模板文件的目录
  • dest= 指明将模板文件拷贝到远程主机的哪个目录下
  • owner= 指明拷贝到远程主机的文件的属主
  • group= 指明拷贝到远程主机的文件的属组
  • mode= 指明拷贝到远程主机的文件的权限

11.setup模块

可收集远程主机的facts变量的信息,相当于收集了目标主机的相关信息(如内核版本、操作系统信息、cpu、…),保存在ansible的内置变量中,之后我们有需要用到时,直接调用变量即可

filter过滤关键字

[root@awx linux]# ansible -i inventory linux -m setup -a 'filter=ansible_all_ipv4_addresses'
192.168.6.44 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.6.44",
            "192.168.6.250",
            "172.17.0.1"
        ],
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

12.fetch模块

从远程主机拉取文件到本地

  • 一般情况下,只会从一个远程节点拉取数据
  • 常见参数有:
  • dest= 从远程主机上拉取的文件存放在本地的位置,一般只能是目录
  • src= 指明远程主机上要拉取的文件,只能是文件,不能是目录
 [root@awx linux]# ansible -i inventory linux -m fetch -a 'src=/etc/passwd dest=/tmp'
192.168.6.44 | CHANGED => {
    "changed": true,
    "checksum": "0908db005cc52e6de0666a0a8eb674f51ea72975",
    "dest": "/tmp/192.168.6.44/etc/passwd",
    "md5sum": "579dfb78b2bfc42c17e5bbd3cab62706",
    "remote_checksum": "0908db005cc52e6de0666a0a8eb674f51ea72975",
    "remote_md5sum": null
}

13.cron模块

管理计划任务的模块

常见参数有:

  • minute= 指明计划任务的分钟,支持格式:0-59,/2等,与正常cron任务定义的一样的语法,省略时,默认为*,也就是每分钟都执行
  • hour= 指明计划任务的小时,支持的语法:0-23,/2等,省略时,默认为*,也就是每小时都执行
    - day= 指明计划任务的天,支持的语法:1-31,/2等,省略时,默认为*,也就是每天都执行
    - month= 指明计划任务的月,支持的语法为:1-12,/2等,省略时,默认为*,也就是每月都执行
    - weekday= 指明计划任务的星期几,支持的语法为:0-6,等,省略时,默认为,也就是每星期几都执行
    - reboot 指明计划任务执行的时间为每次重启之后
    - name= 给该计划任务取个名称,必须要给明。每个任务的名称不能一样。删除任务时,只需要给明任务的名称即可
    - job= 执行的任务是什么,当state=present时才有意义
    - state=present|absent 表示这个任务是创建还是删除,present表示创建,absent表示删除,默认是present
[root@awx linux]# ansible -i inventory linux -m cron -a 'minute=5 hour=*/1  name="test cron" job="echo aaa>>/tmp/aaa" state=present' 
192.168.6.44 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "envs": [],
    "jobs": [
        "test cron"
    ]
}
[root@awx linux]# ansible -i inventory linux -m shell -a "crontab -l"
192.168.6.44 | CHANGED | rc=0 >>
#Ansible: test cron
5 */1 * * * echo aaa>>/tmp/aaa

14.stat模块

注意:对于Windows目标,请改用win_stat模块

检查文件或文件系统的状态

  • path:文件/对象的完整路径(必须)

常用的返回值判断:
 exists: 判断是否存在
 isuid: 调用用户的ID与所有者ID是否匹配

##判断问价是否存在,如果存在执行shell
[root@awx linux]# cat stat.yml 
- hosts: linux
  gather_facts: false
  tasks:
  - name: stat test
    stat: 
      path: /etc/passwd
    register: pp

  - name: shell
    shell: ls /tmp/1.txt -l
    when: pp.stat.exists == true
    register: ls
   
  - name: view ls
    debug:
      msg: "{{ ls.stdout_lines }}"
   
[root@awx linux]# ansible-playbook -i inventory stat.yml 

PLAY [linux] *******************************************************************************************************************************************************************************************************************************

TASK [stat test] ***************************************************************************************************************************************************************************************************************************
ok: [192.168.6.44]

TASK [shell] *******************************************************************************************************************************************************************************************************************************
changed: [192.168.6.44]

TASK [view ls] *****************************************************************************************************************************************************************************************************************************
ok: [192.168.6.44] => {
    "msg": [
        "-rw-r--r-- 1 root root 18 Jan 13 16:09 /tmp/1.txt"
    ]
}

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


五、ansible-playbook

这个 playbook 为一个角色 ‘x’ 指定了如下的行为:

● 如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中
● 如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
● 如果 roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
● 如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依赖” 将被添加到 roles ● 列表中 (1.3 and later)
● 所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路径。
● 所有 script tasks 可以引用 roles/x/files/ 中的脚本,不需要指明文件的路径。
● 所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路径。
● 所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路径

1.ansible获取远程主机ip地址

[root@an1 first]# ansible -i inventory test -m setup -a 'filter=ansible_default_ipv4'
192.168.137.107 | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "192.168.137.107", 
            "alias": "ens33", 
            "broadcast": "192.168.137.255", 
            "gateway": "192.168.137.2", 
            "interface": "ens33", 
            "macaddress": "00:0c:29:1d:b5:38", 
            "mtu": 1500, 
            "netmask": "255.255.255.0", 
            "network": "192.168.137.0", 
            "type": "ether"
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

想要在playbook中精确获取到远程主机ip参考下面配置

[root@an1 first]# vim shell.yml 
- hosts: test
  tasks:
  - name: ss
    shell: echo a = "{{ ansible_default_ipv4.address }}"
    register: free
  - name: ww
    debug:
      msg: "{{ free }}"
[root@an1 first]# ansible-playbook -i inventory shell.yml 

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

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

TASK [ss] **********************************************************************************************************************************************************************************************************************************
changed: [192.168.137.107]

TASK [ww] **********************************************************************************************************************************************************************************************************************************
ok: [192.168.137.107] => {
    "msg": {
        "changed": true, 
        "cmd": "echo a = \"192.168.137.107\"", 
        "delta": "0:00:00.002915", 
        "end": "2022-01-05 16:58:28.322921", 
        "failed": false, 
        "rc": 0, 
        "start": "2022-01-05 16:58:28.320006", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "a = 192.168.137.107", 
        "stdout_lines": [
            "a = 192.168.137.107"
        ]
    }
}

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

2.when语句

如果一个变量存在,你可以使用Jinja2的defined命令执行,不存在,则跳过或掠过.例如:

  当变量存在的时候(foo 被定义的时候),执行对应语句
[root@an1 first]# cat when.yml 
- hosts: test
  tasks:
    - shell: touch {{ foo }}.txt
      when: foo is defined

[root@an1 first]# ansible-playbook -i inventory when.yml 

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

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

TASK [shell] *******************************************************************************************************************************************************************************************************************************
[WARNING]: Consider using the file module with state=touch rather than running 'touch'.  If you need to use command because file is insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
changed: [192.168.137.107]

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


3.循环

(1).with_items

①.标准循环

标准循环是指使用with_items来迭代list类型变量,不仅支持简单的字符串列表,还支持哈希列表

[root@an1 first]# cat with_items.yml 
- hosts: test
  tasks:
  - name: add users
    user: name={{ item }} state=present
    with_items: 
      - user1
      - user2

也可以在变量文件vars中定义,效果和上面一样

list1={“user3”,“user4”}

[root@an1 first]# cat with_items.yml 
- hosts: test
  tasks:
  - name: add users
    user: name={{ item }} state=present
    with_items: "{{ list1 }}"

如果是一个哈希列表,那么可以用以下方式来引用子项:

- name: add users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  with_items:
    - { name: 'user1', groups: 'group1' }
    - { name: 'user2', groups: 'group2' }
②.嵌套循环

嵌套循环就是循环里套循环

- hosts: test
  gather_facts: no
  tasks:
    - name: loops nested loops
      debug: msg="out loops {{ item[0]}}, in loops {{ item[1] }}"
      with_nested:
        - ['Q','W']
        - [1,3,5]

输出结果如下:

[root@an1 first]# ansible-playbook -i inventory with_nested.yml 

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

TASK [loops nested loops] **********************************************************************************************************
ok: [192.168.137.107] => (item=[u'Q', 1]) => {
    "msg": "out loops Q, in loops 1"
}
ok: [192.168.137.107] => (item=[u'Q', 3]) => {
    "msg": "out loops Q, in loops 3"
}
ok: [192.168.137.107] => (item=[u'Q', 5]) => {
    "msg": "out loops Q, in loops 5"
}
ok: [192.168.137.107] => (item=[u'W', 1]) => {
    "msg": "out loops W, in loops 1"
}
ok: [192.168.137.107] => (item=[u'W', 3]) => {
    "msg": "out loops W, in loops 3"
}
ok: [192.168.137.107] => (item=[u'W', 5]) => {
    "msg": "out loops W, in loops 5"
}

PLAY RECAP *************************************************************************************************************************
192.168.137.107            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
③.对哈希表使用循环
- hosts: test
  gather_facts: no
  vars:
    users:
      parker:
        name: Peter Parker
        phone: 321-456-7890
      tom:
        name: Tom
        phone: 678-112-3210
  tasks:
    - name: Print phone records
      debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.phone }})"
      with_dict: "{{ users }}"

通过with_dict来玩转这个哈希表循环,上面代码的输出如下:

[root@an1 first]# ansible-playbook -i inventory hash.yml 

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

TASK [Print phone records] *********************************************************************************************************
ok: [192.168.137.107] => (item={u'key': u'parker', u'value': {u'phone': u'321-456-7890', u'name': u'Peter Parker'}}) => {
    "msg": "User parker is Peter Parker (321-456-7890)"
}
ok: [192.168.137.107] => (item={u'key': u'tom', u'value': {u'phone': u'678-112-3210', u'name': u'Tom'}}) => {
    "msg": "User tom is Tom (678-112-3210)"
}

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

④.对文件列表使用循环

with_fileglob 可以以非递归的方式来模式匹配某一目录下指定格式的文件

- hosts: test
  gather_facts: no
  tasks:
    - name: file loop
      debug: msg="name is {{ item }}"
      with_fileglob:
        - /tmp/*.txt

运行结果如下:

[root@an1 first]# ansible-playbook -i inventory with_fileglob.yml 

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

TASK [file loop] *******************************************************************************************************************
ok: [192.168.137.107] => (item=/tmp/1.txt) => {
    "msg": "name is /tmp/1.txt"
}
ok: [192.168.137.107] => (item=/tmp/2.txt) => {
    "msg": "name is /tmp/2.txt"
}
ok: [192.168.137.107] => (item=/tmp/3.txt) => {
    "msg": "name is /tmp/3.txt"
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

侯侯Hou

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

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

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

打赏作者

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

抵扣说明:

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

余额充值