Handler字段
handler字段定义的任务可以被task
的notify
字段引用,用于该task如果执行的结果为changed(即在远端服务器上完成了实际操作),则被引用的handler执行;反之,则不执行。
handler一般情况都是在所有task执行完之后,若被引用才执行。
若果想让task执行完之后立刻执行引用的handler,可以用meta: flush_handlers
字段。
变量
变量通过vars
字段定义,可以同时定义多个键值对形式的变量,引用变量的格式。还可以将变量分成不同属性,分类引用。如果有大量变量,可以单独使用一个yml文件统一存放变量,通过
vars_files
字段直接引用这个变量文件。
内置变量:ansible-playbook每次执行是都会先收集远程主机的信息,保存到大量的变量中,这些变量我们也可以使用。
ansible test10 -m setup
返回json格式的所有收集到的变量。我们还能够在远端主机中写入一些自定义的信息,这些信息也可以被setup模块收集到。这些信息通常以json或者INI格式被定义在/etc/ansible/facts.d/
目录下的.fact
文件中。1
2
3[testmsg]
msg1=This is the first custom test message
msg2=This is the second custom test message1
2
3
4
5
6{
"testmsg":{
"msg1":"Thsi is the first custom test message",
"msg2":"This is the second custom test message"
}
}1
通过`ansible test10 0m setup -a "filter=ansible_local"`获取自定义信息。
debug用于输出调试信息,引用在远程主机收集的变量信息
anbile_memory_mb.real
,yaml通用的变量引用方式。1
2
3
4
5
6
7
8- hosts: host_all
vars:
testvar: value of test variable
tasks:
- name: debug demo
debug:
var: testvar
msg: "Value of testvar is : {{testvar}}"1
获取远程主机的这些变量不止为了用于输出,我们可以对这些数值进行判断,是否符合我们的要 求,然后执行下一步动作。
注册变量:使用
register
接收task执行完返回的变量即为注册变量。1
2
3
4
5
6
7
8
9
- hosts: host_all
tasks:
- name: test shell
shell: "echo test > /var/testshellfile"
register: testvar
- name: shell module return values
debug:
msg: "{{testvar.cmd}}" # 调用task执行后的注册变量
交互式接收标准输入并写入变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- hosts: host10
tasks:
vars_prompt:
- name: "your_name"
prompt: "Input username"
def1: admin
default: def1 # 没有输入使用默认值
- name: "your_pass"
prompt: "Input your password"
private: no
confirm: yes # 提示用户输入两遍密码
encrypt: "sha512_crypt" # 使用sha512算法对输入的值进行哈希,使用该功能需要先安装passlib库:pip install passlib
tasks:
- name: create user
user:
name: "{{your_name}}"
password: "{{your_pass}}"
- name: output vars
debug:
msg: Your name is {{your_name}},You are {{your_age}} years old.
外部变量:在playbook中引用未定义的变量,可以在执行playbook时指定
ansible-playbook cmdvar.yml --extra-vars "key=value"
通过json格式传入稍微复杂一点的变量。
1
ansible-playbook cmdvar.yml -e '{"countlist":["one","two","three"]}'
在play中如果要引用列表变量终中的指定值时,有如下两种语法:
1
2{{contlist[0]}}
{{contlist.0}}在
ansible/hosts
文件配置主机变量或者主机组变量。1
2
3
4
5
6[testB]
test10 ansible_host=172.17.9.10
test11 ansible_host=172.17.9.11
[testB:vars]
testB_group_var1='group var test'
testB_group_var2='grup var test2'set_fact模块定义变量
1
2
3
4
5
6
7
8
9
10
11
12
13
- hosts:
remote_user: root
vars:
testva1: test1_string
tasks:
- shell: "echo test2_string"
register: shellreturn
- set_fact:
testsf1: "{testvar1}"
testsf2: "{{shellreturn.stdout}}" # 将注册变量赋值给testsf2
- debug:
msg: "{{testsf1}} {{testsf2}}"set_fact变量类似“全局”变量,跟每一个play执行之前都会执行”[Gathering Facts]”的默认任务所收集的fact内置变量一样,这个全局变量可以在之后的所有play中被引用。注册变量也是“全局变量”。
hostvars引用其他主机的fact变量。
1
2
3
4
5
6
7
8
9
10
11
12
- name: "play 1: Gather facts of test10"
hosts: test10
remote_user: root
- name: "play2: Get facts of test10 when operation on test20"
hosts: test20
remote_user: root
tasts:
- debug:
msg: "{{hostvars.test10.ansible_eth0.ipv4}}"
# "{{hostvars['test10'].ansible_eth0.ipv4}}"如果A主机引用B主机的facts,前提是ansible已经收集到B主机的facts才能供A使用,还记不记得每 个play都要执行的默认task”[[Gathering Facts]”,上面我们定义的play1中没有任何task,但是ansible依然会执行默认的收集facts的task,如果将play1删掉,则报错。还可以使用
收集注册变量、hosts中的主机变量、组变量…
默认是不允许跨主机引用vars: [“key1”:”value1”]这种在剧本中定义的主机变量,但是可以使用set_fact字段将其变为全局变量,就可以被hostvars引用了。即通过set_fact结合hostvars的方式,实现跨play获取其他主机中的变量信息的功能。内置变量
以列表形式返回当前play中所有的主机名;
以列表的形式返回hosts中定义的所有主机清单,返回指定组
;
返回主机所在组名称;
vars_files引入变量文件
1
2
3
4
5
6
7
8
9
10
11
12
13
- hosts: group1
remote_user: root
vars_files:
- /root/test/test/bar
tasks:
- debug:
msg: "{{ testvar1 }}, {{ testvar2 }}"
- lineinfile:
path: "/root/test/test/bar"
line: "testvar: ccc"
- debug:
msg: "{{ testvar1 }}, {{ testvar2 }}, {{ testvar3 }}"执行的结果是变量
并没有被打印出来,原因是在变量文件写入之后并没有再次读取变量文件。有什么办法可以动态加载变量文件呢,
include_vars
,include_vars
还可以通过name字段将整个文件的变量赋值给另一个变量。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- hosts: group1
remote_user: root
vars_files:
- /root/test/test/bar
tasks:
- debug:
msg: "{{ testvar1 }}, {{ testvar2 }}"
- lineinfile:
path: "/root/test/test/bar"
line: "testvar: ccc"
- include_vars:
file: /root/test/test/bar
# dir: /root/test/
# file_matching: ["^var.*",test.yaml] # 只加载指定的变量文件
# ignore_files: ["^var_.*",varfile.yaml] # 从上述匹配到的中排除指定变量文件
name: varfile
- debug:
msg: "{{ varfile.testvar1 }}"include_vars
除了可以引入变量文件外,还可以直接使用dir
引入目录下所有以.yaml .yml .json
结尾的所有文件变量,当然也可以通过正则表达式加载指定变量文件,而且是递归加载,depth:1
指定递归深度,要求子目录符合上述要求,否则报错。如果我么你想值本次任务加入了哪些变量文件,通过如下方法:
1
2
3
4
5
6tasks:
- include_vars:
dir: /root/test/test/
register: return_val
- debug:
msg: "{{ return_val.ansible_included_var_files}}"使用上述方式还可以加载一个没有缩进和换行的json文件,以可读格式输出。
、
标签tag
如果只想执行playbook的某些task时,或者执行不执行哪些任务时,可以给task打tag,task的tag继承hosts的tag,他们都可以拥有多个tag。只需要在执行的时候ansible-playbook --tags=tag1 testtag.yml
加上该参数就好了。ansible预置的5种特殊的tag:
- always
- never
- tagged
- untagged
- all
1 |
|
循环(with_item)
反手就是一个demo
1 |
|
循环执行shell模块的返回值会追加放到“results”这个返回值中,所以我们也可以通过“results“关键字获取每次执行后的返回值。
1
2
3
4
5
6
7
8
9
10
11
12
- hosts: test10
tasks:
- name: "play 1"
shell: "{{item}}"
with_items:
- "ls /opt"
- "ls /home"
register: returnvalue
- debug:
msg: "{{item.stdout}}"
with_items: "{{returnvalue.results}}"1
2
3
4
5
6
7
8
9
10
11
12
- hosts: test10
tasks:
- shell: "{{item}}"
with_items:
- "ls /opt"
- "ls /home"
- debug:
msg:
"{% for i in returnvalue.results %}
{{ i.stdout }}
{% endfor %}"上面的例子使用的是jinja2语言中的for循环语法,jinja2是一种模板语言,jinja2是一个基于python的模板引擎。
with_items
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# 第一种语法格式
- hosts: node10
vars:
certdir: "/etc/kubernetes/pki/"
tasks:
- shell: "{{item}}"
with_items:
- "cat {{certdir}}ca.crt"
- "cat {{certdir}}ca.key"
# 第二种语法格式
with_items: [ {{certdir}}ca.crt, {{certdir}}ca.key ]
- hosts: group1
remote_user: root
gather_facts: no
vars:
- cert:
- "/etc/kubernetes/pki/"
- "/root/cfssl/"
tasks:
- shell: "ls {{ item }}"
register: returnvar
with_items:
- "{{ cert }}"
- debug:
msg: "{{ item }}"
with_items:
- "{{ returnvar.results }}"
with_list
1
2
3
4
5
6
7
8
9- hosts: node01
remote_user: root
gather_facts: no
tasks:
- debug:
msg: "{{item}}"
with_list:
- [ 1, 2, 3 ]
- [ a, b ]执行结果:
将
with_list
改成with_itms
的结果:可以看得出来
with_items
是将所有元素放在一个平面当中挨个循环,而with_list
只会循环最外层列表。with_flattened
1
2
3
4
5
6
7
8- hosts: group1
remote_user: root
tasks:
- debug:
msg: "{{ item }}"
with_flattened:
- [ 1, 2, 3 ]
- [ a, b ]效果和
with_items
是完全一样的。with_tagether
1
2
3
4
5
6
7
8- hosts: group1
remote_user: root
tasks:
- debug:
msg: "{{ item }}"
with_together:
- [ 1, 2, 3 ]
- [ a, b ]执行结果:
with_cartesian
1
2
3
4
5
6
7
8
9
10
11
- hosts: group1
remote_user: root
tasks:
- name: "recursion create directory"
file:
state: directory
path: "~/test/test/{{ item.0 }}/{{ item.1 }}"
with_cartesion:
- [ a, b, c ]
- [ test1, test2 ]with_nested
效果同上!
with_indexed_items
1
2
3
4
5
6
7
8
9
10
11
- hosts: node01
remote_user: root
tasks:
- name "show items index"
debug:
msg: "{{ item }}"
with_indexed_items:
- [ test1, test2 ]
- [ test3, [ test4, test5 ]]
- [ test6 ]with_indexed_items
不会像with_flattened
一样将嵌套列表完全扁平化,知识扁平化首层嵌套,第二层的嵌套列表依然当做一个整体元素被打印出来。设定循环起始点和步长
1
2
3
4
5
6
7
8
9
10
11
12
- hosts: group1
remote_user: root
tasks:
- name: "create directory on oushu"
file:
state: directory
path: "/root/test/test{{ item }}"
with_sequence:
start=2
end=6
stride=2with_sequence
还可以指定stride
为负数,即end
小于start
。还可以格式化字符串format。with_random_choice
1
2
3
4with_random_chice:
- 1
- 2
- 3随机返回一个列表。
with_dirt
1
with_subelements
with_file(针对ansible主机)
循环查看文件内容。
with_filelob(针对ansible主机)
1
2
3with_filelob:
- /test/test*
- /etc/systemd/system/*.???????在指定目录中匹配文件名(不匹配目录)。
条件判断when
1 | - |
比较运算符 | 含义 |
---|---|
== | 比较两个对象是否相等,相等为真 |
!= | 比较两个对象是否不等,不等为真 |
> | 比较两个值的大小,右边小为真 |
< | 比较两个值的大小,左边小为真 |
>= | 比较两个值的大小,如果右边的值小或者左右相等,则为真 |
<= | 比较连个值的大小,如果左边的值小或者左右相等,则为真 |
逻辑运算符 | 含义 |
---|---|
and | 逻辑与,同时为真,返回真 |
or | 逻辑或,任意一个为真,返回真 |
not | 取反 |
() | 将一组操作包装在一起 |
写一个判断shell指令是否真确执行的剧本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- hosts: group1
remote_user: root
tasks:
- name: "task: 1"
shell: "ls /root/testabc"
register: return
ignore_errors: true
- name: "task: 2"
debug:
msg: "Command Execution Successful"
when: retuen.rc == 0
- name: "task: 3"
debug:
msg: "Command Execution Failed"
when: retuen.rc != 0条件判断与tests
1
2
3
4
5
6vars:
- testvar: "/root/test.config"
task:
- debug:
msg: "file is exists"
when: not testvar is exists # 这里同样支持逻辑运算符tests测试文件是否存在的时候,也是只针对ansible主机路径,与目标主机没有关系。
判断变量的一些tests:
defined:判断变量是否已经定义,已经定义则返回真
undefind:判断变量是否已经定义,未定义则返回真
none:不判断变量值是否为空,如果变量已经定义,但变量值为空,则返回真1
2
3
4
5
6
7
8
9
10
11
12
13
14
15- hosts: group1
remote_user: root
vars:
testvar: "test"
testvar1:
tasks:
- debug:
msg: "Variable is defined"
when: testvar is defined
- debug:
msg: "Variable is undefined"
when: testvar1 is undefined
- debug:
msg: "Varibale is none"
when: testvar1 is none判断执行结果的tests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- hosts: group1
remote_user: root
vars:
doshell: "yes"
tasks:
- shell: "cat /root/testabc"
register: returnmsg
ignore_errors: true
- debug:
msg: "Success"
when: returnmsg is success
- debug:
msg: "Failed"
when: returnmsg is failure
- debug:
msg: "Changed"
when: returnmsg is change
- debug:
msg: "Skip"
when: returnmsg is skip判断路径的tests
代码就不写了,相对简单。
file:判断路径是否是一个文件,则为真
directory:判断路径是否是一个目录,则为真
link:判断路径是否是一个连接文件,则为真
mount:判断路径是否是一个挂载点,则为真注:上述test是2.6版本中的,在2.5之前某些test需要加上
is_
前缀判断字符串的tests
lower:字符串为纯小写,则为真
upper:字符串为纯大写,则为真这个也是相对简单,字符串可以放在变量中来测试
判断整除的tests
even:判断数值是否为偶数,是偶数则为真
odd:判断数值是否为技术,是奇数则为真
divisibleby(num):判断是否可以整除指定的数值,如果除以指定的值以后余数为0,则返回真subset:判断一个list是不是另一个list的子集,是另一个list的子集时返回真
superset:判断一个list是不是另一个list的父集,是另一个list的父集时返回真
string:潘帆对象是否是一个字符串,是字符串则返回真1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- hosts: group1
remote_user: root
vars:
a:
- 2
- 5
b: [ 1,2,3,4,5 ]
tasks:
- debug:
msg: "A is subset of B"
when: a is subset(b)
- debug:
msg: "B is superset of A"
when: b is superset(a)
异常处理block
1 |
|
rescue
字段会处理同级block
字段中的异常,如果block
中没有报错则不执行rescue
中的步骤。
在block
当中只有单个任务时,看起来和failed
没有什么区别,但是block
还是有优势的,block
和rescue
中均可以由多个任务。
和rescue
同级别的还有always
字段,一看就知道是block
字段中的任务无论成功还是失败都将执行always
中任务。
filed_when
当符合条件判断则退出剧本。
1
2
3
4
5
6
7
8
9
10
- hosts:
remote_user: root
- debug:
msg: "I execute normally"
- shell: "echo 'This is string for testing error'"
register: return_value
failed_when: '"error" in return_value.stdout'
- debug:
msg: "i never execute,Bucause the playbook has stopped"changed_when
faled_when是将符合条件的任务设置为failed状态,那么
changed_when
就是将符合条件的任务设置为changed
状态。除了上述功能外,满足条件让对应的任务永远不能是changed状态。chagne_when=true
。changed_when还可以配合handler使用,
过滤器
跟字符串操作相关的过滤器
字符串相关 | 含义 | |
---|---|---|
upper | 转换纯大写[列表适用] | |
lower | 转换纯小写[列表适用] | |
reverse | 将字符创翻转 | |
first | 返回第一个字符,[列表适用] | |
last | 返回最后一个字符,[列表适用] | |
length | 返回字符创长度,与count等效,[列表适用] | |
list | 将字符串转换成列表,每个字符串为元素 | |
shuffle | 将字符创转换成列表,并打乱顺序,[列表适用] | |
数字相关 | 含义 | |
int() | 转换字整型数字,小括号可设置默认值int(default=6) | |
float() | 浮点型小数,小括号内可以直接写默认值 | |
abs | 返回绝对值 | |
round() | 四舍五入,小括号内可以执行保留小数点后几位 | |
random() | 返回一个随机数`10 | random(start=5,step=3)` |
列表相关 | 含义 | |
min | 返回列表中的最大值 | |
max | 返回列表中的最小值 | |
sort(reverse=true) | 升序排列,降序(reverse=true) | |
sum | 返回纯数字非嵌套列表中的所有数字的和 | |
flatten(levels=1) | “拉平”嵌套列表,小括号可指定拉平几层嵌套 | |
join() | 将列表中的元素合并成一个字符串,小括号可指定元素之间的间隔 | |
random() | 从列表中随机返回一个元素,小括号指定随机种子 | |
union() | `list1 | union(list2)`返回两个列表的并集 |
intersect() | 返回两个列表的交集 | |
difference() | `list1 | difference(list2)`返回存在于list1但不存在list2中的元素 |
symmetric_difference() | 返回两个列表的并集,且不包含交集 |
1 | {"logs":[{"domainName":"asia1.cdn.test.com","files":[{"dateFrom":"2018-09-05-0000","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a","fileSize":254,"fileName":"2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz","fileMd5":"error"}]},{"domainName":"image1.cdn.test.com","files":[{"dateFrom":"2018-09-05-2200","dateTo":"2018-09-05-2259","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c","fileSize":10509,"fileName":"2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz","fileMd5":"error"},{"dateFrom":"2018-09-05-2300","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe","fileSize":5637,"fileName":"2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz","fileMd5":"error"}]}]} |
一个没有缩进的json文件,返回数据总所有的logUrl:
1 |
|
1 |
|