一: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