在使用ansible做自動化運維的時候,大多數情況下都執行某些任務的時候都需要依賴某個變量的值或者是上一個任務的執行結果。如,根據facts信息中的系統版本相關的信息來確定使用哪種包管理器安裝軟件。Ansible提供when語句,可以控制任務的執行流程。
一個很簡單的when語句的例子:
|
1
2
3
4
|
tasks:
-
name:
"shutdown Debian flavored systems"
command:
/
sbin
/
shutdown
-
t now
when: ansible_os_family
=
=
"Debian
|
表示當節點主機系統為Debian的時候,執行關機操作。
在符合語句中也可以使用小括號:
|
1
2
3
4
5
|
tasks:
-
name:
"shutdown CentOS 6 and 7 systems"
command:
/
sbin
/
shutdown
-
t now
when: ansible_distribution
=
=
"CentOS"
and
(ansible_distribution_major_version
=
=
"6"
or
ansible_distribution_major_version
=
=
"7"
)
|
在`when`語句中也可以使用過濾器。如,我們想跳過一個語句執行中的錯誤,但是后續的任務的執行需要由該任務是否成功執行決定:
|
1
2
3
4
5
6
7
8
9
10
|
tasks:
-
command:
/
bin
/
false
register: result
ignore_errors:
True
-
command:
/
bin
/
something
when: result|failed
-
command:
/
bin
/
something_else
when: result|success
-
command:
/
bin
/
still
/
something_else
when: result|skipped
|
有時候需要將一個字符串的變量轉換為整數來進行數字比較:
|
1
2
3
|
tasks:
-
shell: echo
"only on Red Hat 6, derivatives, and later"
when: ansible_os_family
=
=
"RedHat"
and
ansible_lsb.major_release|
int
>
=
6
|
在playbooks和inventory中定義的變量都可以使用,如,需要根據一個變量的bool值決定是否執行該任務:
|
1
2
|
vars
:
epic: true
|
條件語句:
|
1
2
3
|
tasks:
-
shell: echo
"This certainly is epic!"
when: epic
|
或:
|
1
2
3
|
tasks:
-
shell: echo
"This certainly isn't epic!"
when:
not
epic
|
如果引用的變量沒有被定義,使用Jinja2的`defined`測試,可以跳過或者是拋出錯誤:
|
1
2
3
4
5
6
|
tasks:
-
shell: echo
"I've got '{{ foo }}' and am not afraid to use it!"
when: foo
is
defined
-
fail: msg
=
"Bailing out. this play requires 'bar'"
when: bar
is
not
defined
|
當`when`和`with_items`一起使用的時候,每個項都會單獨被`when`語句處理:
|
1
2
3
4
|
tasks:
-
command: echo {{ item }}
with_items: [
0
,
2
,
4
,
6
,
8
,
10
]
when: item >
5
|
示例:
|
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
|
[root@web1 ~]
# cat /etc/ansible/when.yml
-
-
-
-
hosts: webservers
remote_user: root
tasks:
-
command: echo {{ item }}
with_items: [
1
,
2
,
3
,
4
,
5
,
6
,
8
,
10
]
when: item >
5
[root@web1 ~]
# ansible-playbook /etc/ansible/when.yml
PLAY [webservers]
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
GATHERING FACTS
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
ok: [
192.168
.
1.65
]
TASK: [command echo {{ item }}]
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
skipping: [
192.168
.
1.65
]
=
> (item
=
1
)
skipping: [
192.168
.
1.65
]
=
> (item
=
2
)
skipping: [
192.168
.
1.65
]
=
> (item
=
3
)
skipping: [
192.168
.
1.65
]
=
> (item
=
4
)
skipping: [
192.168
.
1.65
]
=
> (item
=
5
)
changed: [
192.168
.
1.65
]
=
> (item
=
6
)
changed: [
192.168
.
1.65
]
=
> (item
=
8
)
changed: [
192.168
.
1.65
]
=
> (item
=
10
)
PLAY RECAP
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
192.168
.
1.65
: ok
=
2
changed
=
1
unreachable
=
0
failed
=
0
|
如果需要的話,也可以返回自定義的facts給控制節點。返回的自定義的facts變量也可以用作下個任務的執行條件:
|
1
2
3
4
5
|
tasks:
-
name: gather site specific fact data
action: site_facts
-
command:
/
usr
/
bin
/
thingy
when: my_custom_fact_just_retrieved_from_the_remote_system
=
=
'1234'
|
在角色和包含中使用when
如果有多個任務都需要使用同一個條件語句控制。可以將這些任務打包到一個單獨的任務文件中,然后使用`include`包含和`when`條件語句。條件語句只對包含任務文件起作用,對包含playbook文件不起作用。指定的條件語句會作用到所包含的每個任務上:
|
1
2
|
-
include: tasks
/
sometasks.yml
when:
"'reticulating splines' in output"
|
角色中使用when
|
1
2
3
|
-
hosts: webservers
roles:
-
{ role: debian_stock_config, when: ansible_os_family
=
=
'Debian'
}
|
注冊變量
在playbook中將某個命令運行的結果保存起來,提供給后續任務使用。如,通過command模塊來判斷遠程節點上某個文件是否存在或者通過執行某個命令的獲取其返回結果,並保存起來,下個任務根據獲取的變量值來決定執行的具體操作。
register關鍵字可以將任務執行結果保存到一個變量中,該變量可以在模板或者playbooks文件中使用:
|
1
2
3
4
5
6
7
8
9
10
|
-
name: test play
hosts:
all
tasks:
-
shell: cat
/
etc
/
motd
register: motd_contents
-
shell: echo
"motd contains the word hi"
when: motd_contents.stdout.find(
'hi'
) !
=
-
1
|
上邊中的例子中,通過注冊變量訪問返回的內容,`stdout`里面保存了命令的標准輸出內容。注冊變量還可以使用在`with_items`中,如果其保存的內容可以轉換為列表,或者內容本身就是個列表。如果命令的輸出本身就是列表,可以通過`stdout_lines`訪問:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
name: registered variable usage as a with_items
list
hosts:
all
tasks:
-
name: retrieve the
list
of home directories
command: ls
/
home
register: home_dirs
-
name: add home dirs to the backup spooler
file
: path
=
/
mnt
/
bkspool
/
{{ item }} src
=
/
home
/
{{ item }} state
=
link
with_items: home_dirs.stdout_lines
# same as with_items: home_dirs.stdout.split()
|
示例:
|
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
29
30
31
32
33
34
35
36
|
[root@web1 ~]
# cat /etc/ansible/rewith.yml
-
-
-
-
hosts: webservers
remote_user: root
tasks:
-
name:
list
of home
dir
command: ls
/
home
register: home_dirs
-
name: add home dirs to the backup
file
: path
=
/
tmp
/
back
/
{{ item }} src
=
/
home
/
{{ item }} state
=
link
with_items: home_dirs.stdout_lines
[root@web1 ~]
# ansible-playbook /etc/ansible/rewith.yml
PLAY [webservers]
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
GATHERING FACTS
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
ok: [
192.168
.
1.65
]
TASK: [
list
of home
dir
]
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
changed: [
192.168
.
1.65
]
TASK: [add home dirs to the backup]
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
changed: [
192.168
.
1.65
]
=
> (item
=
1.sql
)
changed: [
192.168
.
1.65
]
=
> (item
=
1youku
.sql)
changed: [
192.168
.
1.65
]
=
> (item
=
liuzhenwei)
changed: [
192.168
.
1.65
]
=
> (item
=
tom)
PLAY RECAP
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
192.168
.
1.65
: ok
=
3
changed
=
2
unreachable
=
0
failed
=
0
###遠程節點
[root@db2 ~]
# ll /tmp/back
total
0
lrwxrwxrwx.
1
root root
11
Aug
4
14
:
37
1.sql
-
>
/
home
/
1.sql
lrwxrwxrwx.
1
root root
16
Aug
4
14
:
37
1youku
.sql
-
>
/
home
/
1youku
.sql
lrwxrwxrwx.
1
root root
16
Aug
4
14
:
37
liuzhenwei
-
>
/
home
/
liuzhenwei
lrwxrwxrwx.
1
root root
9
Aug
4
14
:
37
tom
-
>
/
home
/
tom
|
在ansible中when語句的使用還是比較多的,它可以用來控制playbooks中任務的執行流程。類似於程序中的條件語句一樣,使得ansible可以更好的按照運維人員的意願來對遠程節點執行特定的操作。
