循环
with_items 迭代列表
- “{{ item }}”
- with_items:
with_dict 迭代字典
- “{{ item.key }}”
- “{{ item.value }}”
- with_dict:
- KEY:VALUE
with_fileglob 迭代文件
可以使用多个文件。
- “{{ item }}”
- with_filegblob: /xxx/*.xx
with_lines 迭代行
- “{{ item }}”
- with_lines: find 路径 …
with_nested 套嵌迭代
从 0 开始。
- “{{ item[NUM] }}”
- with_nested: [xxx,xxx,xxx,…]
with_sequence 排序列
start:开始
end:结束
stride:每隔
- “{{ item }}”
- with_sequence:
- start=NUM
- start=NUM
- stride=NUM
with_random_choice 随机获得列表中的一个值
- “{{ item }}”
- with_random_choice:
Loop
现在 loop 已经替代了 with,更多的是 loop 配合过滤器进行使用。
“{{ 变量 | 过滤器 }}”
字符串有关的过滤器:
- upper 将字符串转换成纯大写。
- lower 将字符串转换成纯小写。
- trim 将字符串开头和结尾的空格去掉。
- length 求字符串的长度。
- capitalize 将字符串首字母大写,之后的所有字母纯小写。
- first 返回字符串的第一个字符。
- last 返回字符串的最后一个字符。
- center(width=30) 将字符串放在中间,并且设置字符串的长度为 30,字符串两边用空格补齐 30 位长。
- length OR count 返回字符串长度。
- list 将字符串转换成列表,每个字符作为一个元素。
- shuffle 将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序。
和数字有关的过滤器:
ansible 中,字符串和整形不能直接计算,比如 {{ 8+‘8’ }} 会报错。
如果无法转换,默认返回 0;使用 int(default=6) 或者 int(6) 时,如果无法转换 int 类型,则返回指定值 6。
- int 整型。
- float 浮点型。
- abs 绝对值。
- round 四舍五入,round(5) 取小数点后五位。
- random 从 0 到 100 中随机返回一个随机数;“{{ 10 | random(start=5) }}” 从 5 到 10 中随机返回一个随机数;“{{ 15 | random(start=5,step=3) }}” 从 5 到 15 中随机返回一个随机数,步长为 3。
文件或目录类过滤器:
- hash(‘sha1’) 使用 sha1 算法对字符串进行哈希。
- hash(‘md5’) 使用 md5 算法对字符串进行哈希。
- checksum 获取到字符串的校验和,与 md5 哈希值一致。
- password_hash(‘sha256’) 使用 sha256 算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值。
- password_hash(‘sha256’,‘指定字符串’) 使用 sha256 算法对字符串进行哈希,并使用指定的字符串作为"盐"。
- password_hash(‘sha512’) 使用 sha512 算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值。
判断
- When。
- 判断运算符:“==” “!=” “>” “<” “>=” “<=” “and” “or” “not” “in” “not in” 。
- 每次执行完一个任务,不管成功与失败,都会将执行的结果进行注册,可以使用这个注册的变量来 when。
- 判断变量的一些 tests:
- Defined:判断变量是否已经定义,已定义则返真。
- Undefined:判断变量是否已经定义,未定义则返真。
- None:判断变量值是否为空,如果变量已经定义,但是变量值为空,则返真。
- 判断执行结果的一些 tests:
- Success/successed:通过任务的返回信息判断执行状态,任务执行成功返回真。
- Failure/failed:通过执行任务的返回信息判断执行状态,任务执行失败则返回真。
- Change/changed:通过任务的返回信息判断执行状态,任务返回状态为 changed 则返回真。
- Skip/skipped:通过任务的返回信息判断执行状态,当任务没有满足条件,而被跳过执行,则返回真。
- 判断路径的一些 tests(ansible 主机中的路径,与目标主机无关):
- file:判断路径是否是一个文件。
- directory:判断路径是否是一个目录。
- link:判断路径是否是一个软连接。
- mount:判断路径是否是一个挂载点。
- exists:判断路径是否存在。
- 判断字符串的一些 tests:
- lower:判断包含字母的字符串中的字母是否纯小写。
- upper:判断包含字母的字符串中的字母是否纯大写。
- 其它的一些 tests:
- string:判断对象是否是一个字符串。
- number:判断对象是否一个数字。
block/rescue/always:限制性 block,如果执行失败,则执行 rescue,无论是 block 还是 rescue 执行失败还是成功,在最后都执行 always。
failed_when
hash 加密
例:
password: “{{ ‘redhat’ | password_hash(‘sha512’ )}}”
跳过错误、忽略错误
ignore_errors: yes
changed_when 修改任务执行后的最终状态
- changed_when: true
- changed_when: false
练习
要求:
- 给 node1 添加一块 5G 的硬盘;给 node2 添加一块 2G 的硬盘;node3 不添加硬盘。
- 写一个 partition.yml 的 playbook,满足如下要求:
- 给所有的受控主机创建分区,创建 2500M 的分区,然后对分区进行格式化,格式化为 xfs 的文件系统。
- 如果不能满足创建 2500M 的分区,则显示错误消息为:disk size not enough,接着改为创建 1000M。
- 如果没有 /dev/sdb 硬盘,则显示错误消息为:the device is not sdb
添加硬盘
[root@node1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─cs-root 253:0 0 17G 0 lvm /
└─cs-swap 253:1 0 2G 0 lvm [SWAP]
sdb 8:16 0 5G 0 disk
sr0 11:0 1 9G 0 rom
[root@node2 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─cs-root 253:0 0 17G 0 lvm /
└─cs-swap 253:1 0 2G 0 lvm [SWAP]
sdb 8:16 0 2G 0 disk
sr0 11:0 1 9G 0 rom
[root@node3 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─cs-root 253:0 0 17G 0 lvm /
└─cs-swap 253:1 0 2G 0 lvm [SWAP]
sr0 11:0 1 9G 0 rom
playbook
[root@server ~]# su - student
Last login: Fri Oct 28 15:08:17 CST 2022 on pts/0
[student@server ~]$ cd ansible/
[student@server ansible]$ vim partition.yml
---
- name: parted for node1
hosts: all
tasks:
- name: create partition 2500M
block:
- name: parted
parted:
device: /dev/sdb
number: 1
part_type: primary
part_start: 10MiB
part_end: 2510MiB
state: present
rescue:
- name: output fail message
debug:
msg: disk size not enough.
- name: create partition 1000M
parted:
device: /dev/sdb
number: 1
part_type: primary
part_start: 10MiB
part_end: 1010MiB
state: present
always:
- name: format
filesystem:
fstype: xfs
dev: /dev/sdb
when: "ansible_devices.sdb is defined"
- name: search not exists
debug:
msg: the device is not sdb
when: "ansible_devices.sdb is not defined"
执行 playbook
[student@server ansible]$ ansible-playbook partition.yml
PLAY [parted for node1] ********************************************************
TASK [Gathering Facts] *********************************************************
ok: [node2]
ok: [node3]
ok: [node1]
TASK [parted] ******************************************************************
skipping: [node3]
fatal: [node2]: FAILED! => {"changed": false, "err": "Error: The location 2510MiB is outside of the device /dev/sdb.\n", "msg": "Error while running parted script: /sbin/parted -s -m -a optimal /dev/sdb -- unit KiB mklabel msdos mkpart primary 10MiB 2510MiB", "out": "", "rc": 1}
changed: [node1]
TASK [output fail message] *****************************************************
ok: [node2] => {
"msg": "disk size not enough."
}
TASK [create partition 1000M] **************************************************
changed: [node2]
TASK [format] ******************************************************************
skipping: [node3]
changed: [node2]
changed: [node1]
TASK [search not exists] *******************************************************
skipping: [node1]
skipping: [node2]
ok: [node3] => {
"msg": "the device is not sdb"
}
PLAY RECAP *********************************************************************
node1 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node2 : ok=4 changed=2 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0
node3 : ok=2 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0