当前位置: 首页 > news >正文

台山网站开发网络培训心得体会

台山网站开发,网络培训心得体会,wordpress怎么加rrs,做网站开发需要学哪些东西环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 循环的方法 loopwith_<lookup>until 用这几种方式都可以实现循环。其中&#xff0c; loop 是推荐的用法&#xff0c;在很多时候能够替换 with_<lookup> 。 loop…

环境

  • 管理节点:Ubuntu 22.04
  • 控制节点:CentOS 8
  • Ansible:2.15.6

循环的方法

  • loop
  • with_<lookup>
  • until

用这几种方式都可以实现循环。其中, loop 是推荐的用法,在很多时候能够替换 with_<lookup>

loopwith_<lookup>

with_<lookup> 使用了lookup插件,比如 with_items 使用的是 items lookup。(注:可参见我另一篇文档。)

loop 等同于 with_list 。注意, loop 是作用在list上的,如果用在字符串上会报错。

---
- hosts: alltasks:- name: task1debug:msg: "{{ item }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"- name: task2debug:msg: "{{ item }}"with_list: "{{ ['aaa', 'bbb', 'ccc'] }}"- name: task3debug:msg: "{{ item }}"with_items: "{{ ['aaa', 'bbb', 'ccc'] }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task3] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}

可见,本例中 loopwith_listwith_items 的效果是一样的。

但是对于嵌套的list, loopwith_items 并不是完全等同的。

......- name: task4debug:msg: "{{ item }}"loop: "{{ ['aaa', ['bbb', ['ddd', 'eee']], 'ccc'] }}"- name: task5debug:msg: "{{ item }}"with_items: "{{ ['aaa', ['bbb', ['ddd', 'eee']], 'ccc'] }}"
......

运行结果如下:

TASK [task4] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=['bbb', ['ddd', 'eee']]) => {"msg": ["bbb",["ddd","eee"]]
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task5] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=['ddd', 'eee']) => {"msg": ["ddd","eee"]
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}

可见:

  • loop 只针对最外层的list,不管是否有嵌套。
  • with_items 则是解开了第一层嵌套的list。这个行为比较诡异,要么就不要管嵌套,要么就全部处理,为什么只处理第一层嵌套呢?

实际上,对于 loop ,可用 flatten filter来指定解开嵌套:

(注:flatten是扁平化的意思,这里的扁平化和Java8里扁平化流的概念类似,即把层次结构转换为线性结构)

......- name: task6debug:msg: "{{ item }}"loop: "{{ ['aaa', ['bbb', ['ddd', 'eee']], 'ccc'] | flatten }}"- name: task7debug:msg: "{{ item }}"loop: "{{ ['aaa', ['bbb', ['ddd', 'eee']], 'ccc'] | flatten(levels=1) }}"
......

运行结果如下:

TASK [task6] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ddd) => {"msg": "ddd"
}
ok: [192.168.1.55] => (item=eee) => {"msg": "eee"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task7] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=['ddd', 'eee']) => {"msg": ["ddd","eee"]
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}

可见, flatten 默认会处理所有嵌套,也可以通过 levels 选项,指定处理几层嵌套。

由于 with_items 处理一层嵌套,所以, with_items 就相当于 loop 指定了 flatten(levels=1) 。在本例中,task5和task7的运行结果是一样的。

需要使用 lookup 的循环,多使用 with_<lookup> 语句,而不是 loop 语句。比如:

---
- hosts: alltasks:- name: task1debug:msg: "{{ item }}"loop: "{{ lookup('fileglob', '/tmp/*.txt', wantlist=True) }}"- name: task2debug:msg: "{{ item }}"with_fileglob: "/tmp/*.txt"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=/tmp/b.txt) => {"msg": "/tmp/b.txt"
}
ok: [192.168.1.55] => (item=/tmp/a.txt) => {"msg": "/tmp/a.txt"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => (item=/tmp/b.txt) => {"msg": "/tmp/b.txt"
}
ok: [192.168.1.55] => (item=/tmp/a.txt) => {"msg": "/tmp/a.txt"
}

显然,此处使用 with_fileglob 比使用 loop 要简洁。

注: fileglob 获取指定目录下符合条件的文件名(不包含子目录)。

循环的种类

简单list

---
- hosts: allvars:var1: ['aaa', 'bbb', 'ccc']tasks:- name: task1 # list常量debug:msg: "{{ item }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"# loop: ['aaa', 'bbb', 'ccc'] 可以简写- name: task2 # list常量debug:msg: "{{ item }}"loop:- aaa # 引号可以省略- "bbb"- "ccc"- name: task3 # list变量debug:msg: "{{ item }}"loop: "{{ var1 }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}TASK [task3] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ccc"
}

复杂list

---
- hosts: allvars:var1: [{name: "Tom", age: 20}, {name: "Jerry", age: 18}]tasks:- name: task1debug:msg: "Name: {{ item.name }}. Age: {{ item.age }}"loop: "{{ [{ 'name': 'Tom', 'age': 20 }, { 'name': 'Jerry', 'age': 18 }] }}"#loop: "{{ [{ name: 'Tom', age: 20 }, { name: 'Jerry', age: 18 }] }}" # 报错!说name未定义#loop: [{ name: 'Tom', age: 20 }, { name: 'Jerry', age: 18 }] # OK#loop: [{ 'name': 'Tom', 'age': 20 }, { 'name': 'Jerry', 'age': 18 }] # OK- name: task2debug:msg: "Name: {{ item.name }}. Age: {{ item.age }}"loop:- { name: "Tom", age: 20 }- { name: "Jerry", age: 18 }- name: task3debug:msg: "Name: {{ item.name }}. Age: {{ item.age }}"loop: "{{ var1 }}"

可以看到,对于key要不要加引号,行为好像有点诡异,最好还是加上吧。

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item={'name': 'Tom', 'age': 20}) => {"msg": "Name: Tom. Age: 20"
}
ok: [192.168.1.55] => (item={'name': 'Jerry', 'age': 18}) => {"msg": "Name: Jerry. Age: 18"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => (item={'name': 'Tom', 'age': 20}) => {"msg": "Name: Tom. Age: 20"
}
ok: [192.168.1.55] => (item={'name': 'Jerry', 'age': 18}) => {"msg": "Name: Jerry. Age: 18"
}TASK [task3] ***************************************************************************************
ok: [192.168.1.55] => (item={'name': 'Tom', 'age': 20}) => {"msg": "Name: Tom. Age: 20"
}
ok: [192.168.1.55] => (item={'name': 'Jerry', 'age': 18}) => {"msg": "Name: Jerry. Age: 18"
}

dict

如果要遍历一个dict,则需要使用 dict2items filter,将其转换为list:

---
- hosts: allvars:var1: {name: "Tom", age: 20}tasks:- name: task1debug:msg: "Key: {{ item.key }}. Value: {{ item.value }}"loop: "{{ {'name': 'Tom', 'age': 20} | dict2items }}"- name: task2debug:msg: "Key: {{ item.key }}. Value: {{ item.value }}"loop: "{{ var1 | dict2items }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item={'key': 'name', 'value': 'Tom'}) => {"msg": "Key: name. Value: Tom"
}
ok: [192.168.1.55] => (item={'key': 'age', 'value': 20}) => {"msg": "Key: age. Value: 20"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => (item={'key': 'name', 'value': 'Tom'}) => {"msg": "Key: name. Value: Tom"
}
ok: [192.168.1.55] => (item={'key': 'age', 'value': 20}) => {"msg": "Key: age. Value: 20"
}

本例中,dict为:

{name: "Tom", age: 20}

转为list后:

    [{"key": "name","value": "Tom"},{"key": "age","value": 20}]

循环结果的register变量

---
- hosts: alltasks:- name: task1shell: "echo {{ item }}"loop: "{{ ['aaa', 'bbb'] }}"register: var1- name: task2debug:msg: "{{ var1 }}"

运行结果如下:

TASK [task1] ***************************************************************************************
changed: [192.168.1.55] => (item=aaa)
changed: [192.168.1.55] => (item=bbb)TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => {"msg": {"changed": true,"msg": "All items completed","results": [{"ansible_loop_var": "item","changed": true,"cmd": "echo aaa","delta": "0:00:00.002332","end": "2023-11-21 22:29:54.990234","failed": false,"invocation": {"module_args": {"_raw_params": "echo aaa","_uses_shell": true,"argv": null,"chdir": null,"creates": null,"executable": null,"removes": null,"stdin": null,"stdin_add_newline": true,"strip_empty_ends": true}},"item": "aaa","msg": "","rc": 0,"start": "2023-11-21 22:29:54.987902","stderr": "","stderr_lines": [],"stdout": "aaa","stdout_lines": ["aaa"]},{"ansible_loop_var": "item","changed": true,"cmd": "echo bbb","delta": "0:00:00.002036","end": "2023-11-21 22:29:55.223227","failed": false,"invocation": {"module_args": {"_raw_params": "echo bbb","_uses_shell": true,"argv": null,"chdir": null,"creates": null,"executable": null,"removes": null,"stdin": null,"stdin_add_newline": true,"strip_empty_ends": true}},"item": "bbb","msg": "","rc": 0,"start": "2023-11-21 22:29:55.221191","stderr": "","stderr_lines": [],"stdout": "bbb","stdout_lines": ["bbb"]}],"skipped": false}
}

可见,register变量把循环操作的结果放到了叫做 results 的list里。因此,后续可以遍历 results ,做相应处理,比如:

---
- hosts: alltasks:- name: task1shell: "cat {{ item }}"loop: "{{ ['/tmp/a.txt', '/tmp/d.txt'] }}"register: var1ignore_errors: true- name: task2debug:msg: "{{ var1 }}"- name: task3fail:msg: "Something is wrong!"when: item.rc != 0loop: "{{ var1.results }}"

假设 /tmp/d.txt 不存在,则运行结果如下:

TASK [task1] ***************************************************************************************
changed: [192.168.1.55] => (item=/tmp/a.txt)
failed: [192.168.1.55] (item=/tmp/d.txt) => {"ansible_loop_var": "item", "changed": true, "cmd": "cat /tmp/d.txt", "delta": "0:00:00.002438", "end": "2023-11-21 22:46:28.216904", "item": "/tmp/d.txt", "msg": "non-zero return code", "rc": 1, "start": "2023-11-21 22:46:28.214466", "stderr": "cat: /tmp/d.txt: No such file or directory", "stderr_lines": ["cat: /tmp/d.txt: No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoringTASK [task2] ***************************************************************************************
ok: [192.168.1.55] => {"msg": {"changed": true,"failed": true,"msg": "One or more items failed","results": [{"ansible_loop_var": "item","changed": true,"cmd": "cat /tmp/a.txt","delta": "0:00:00.003006","end": "2023-11-21 22:46:27.995302","failed": false,"invocation": {"module_args": {"_raw_params": "cat /tmp/a.txt","_uses_shell": true,"argv": null,"chdir": null,"creates": null,"executable": null,"removes": null,"stdin": null,"stdin_add_newline": true,"strip_empty_ends": true}},"item": "/tmp/a.txt","msg": "","rc": 0,"start": "2023-11-21 22:46:27.992296","stderr": "","stderr_lines": [],"stdout": "aaaaa\nb\nccccc","stdout_lines": ["aaaaa","b","ccccc"]},{"ansible_loop_var": "item","changed": true,"cmd": "cat /tmp/d.txt","delta": "0:00:00.002438","end": "2023-11-21 22:46:28.216904","failed": true,"invocation": {"module_args": {"_raw_params": "cat /tmp/d.txt","_uses_shell": true,"argv": null,"chdir": null,"creates": null,"executable": null,"removes": null,"stdin": null,"stdin_add_newline": true,"strip_empty_ends": true}},"item": "/tmp/d.txt","msg": "non-zero return code","rc": 1,"start": "2023-11-21 22:46:28.214466","stderr": "cat: /tmp/d.txt: No such file or directory","stderr_lines": ["cat: /tmp/d.txt: No such file or directory"],"stdout": "","stdout_lines": []}],"skipped": false}
}TASK [task3] ***************************************************************************************
skipping: [192.168.1.55] => (item={'changed': True, 'stdout': 'aaaaa\nb\nccccc', 'stderr': '', 'rc': 0, 'cmd': 'cat /tmp/a.txt', 'start': '2023-11-21 22:46:27.992296', 'end': '2023-11-21 22:46:27.995302', 'delta': '0:00:00.003006', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'cat /tmp/a.txt', '_uses_shell': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['aaaaa', 'b', 'ccccc'], 'stderr_lines': [], 'failed': False, 'item': '/tmp/a.txt', 'ansible_loop_var': 'item'}) 
failed: [192.168.1.55] (item={'changed': True, 'stdout': '', 'stderr': 'cat: /tmp/d.txt: No such file or directory', 'rc': 1, 'cmd': 'cat /tmp/d.txt', 'start': '2023-11-21 22:46:28.214466', 'end': '2023-11-21 22:46:28.216904', 'delta': '0:00:00.002438', 'failed': True, 'msg': 'non-zero return code', 'invocation': {'module_args': {'_raw_params': 'cat /tmp/d.txt', '_uses_shell': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': [], 'stderr_lines': ['cat: /tmp/d.txt: No such file or directory'], 'item': '/tmp/d.txt', 'ansible_loop_var': 'item'}) => {"ansible_loop_var": "item", "changed": false, "item": {"ansible_loop_var": "item", "changed": true, "cmd": "cat /tmp/d.txt", "delta": "0:00:00.002438", "end": "2023-11-21 22:46:28.216904", "failed": true, "invocation": {"module_args": {"_raw_params": "cat /tmp/d.txt", "_uses_shell": true, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true}}, "item": "/tmp/d.txt", "msg": "non-zero return code", "rc": 1, "start": "2023-11-21 22:46:28.214466", "stderr": "cat: /tmp/d.txt: No such file or directory", "stderr_lines": ["cat: /tmp/d.txt: No such file or directory"], "stdout": "", "stdout_lines": []}, "msg": "Something is wrong!"}

本例中,由于 /tmp/d.txt 不存在, results 的第2个元素,其rc值为1。

注意:每一次迭代,其结果就会放到register变量里,而不是整个循环结束后才放的。

---
- hosts: alltasks:- name: task1shell: echo "{{ item }}"loop:- "aaa"- "bbb"register: var1changed_when: var1.stdout != "aaa"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa)
changed: [192.168.1.55] => (item=bbb)

可见,第一次迭代没有满足判断条件,而第二次迭代满足判断条件了。

复杂循环

遍历嵌套list

---
- hosts: alltasks:- name: task1debug:msg: "{{ item[0] }} {{ item[1] }}"loop: "{{ ['Zhang', 'Li'] | product(['San', 'Si']) | list }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=['Zhang', 'San']) => {"msg": "Zhang San"
}
ok: [192.168.1.55] => (item=['Zhang', 'Si']) => {"msg": "Zhang Si"
}
ok: [192.168.1.55] => (item=['Li', 'San']) => {"msg": "Li San"
}
ok: [192.168.1.55] => (item=['Li', 'Si']) => {"msg": "Li Si"
}

本例中,把两个list做笛卡尔乘积,生成了一个新的嵌套list:

    [["Zhang","San"],["Zhang","Si"],["Li","San"],["Li","Si"]]

然后遍历外层list,并通过 item[0]item[1] 访问内层list的元素。

Retry

---
- hosts: alltasks:- name: task1shell: cat /tmp/a.txtregister: var1until: var1.stdout.find("OK") != -1retries: 3delay: 5

运行结果如下:

TASK [task1] ***************************************************************************************
FAILED - RETRYING: [192.168.1.55]: task1 (3 retries left).
FAILED - RETRYING: [192.168.1.55]: task1 (2 retries left).
FAILED - RETRYING: [192.168.1.55]: task1 (1 retries left).
fatal: [192.168.1.55]: FAILED! => {"attempts": 3, "changed": true, "cmd": "cat /tmp/a.txt", "delta": "0:00:00.002228", "end": "2023-11-23 07:53:18.333193", "msg": "", "rc": 0, "start": "2023-11-23 07:53:18.330965", "stderr": "", "stderr_lines": [], "stdout": "aaaaa\nb\nccccc", "stdout_lines": ["aaaaa", "b", "ccccc"]}

在运行过程中,编辑 /tmp/a.txt 文件(注意是在目标机器上),添加 OK 的内容,则运行结果如下:

TASK [task1] ***************************************************************************************
FAILED - RETRYING: [192.168.1.55]: task1 (3 retries left).
FAILED - RETRYING: [192.168.1.55]: task1 (2 retries left).
changed: [192.168.1.55]

注:

  • retries 的缺省值是 3delay 的缺省值是 5

遍历inventory

假设 /etc/ansible/hosts 内容如下:

[myvms]
192.168.1.55[myself]
127.0.0.1
---
- hosts: alltasks:- name: task1debug:msg: "{{ item }}"loop: "{{ groups['all'] }}"#loop: "{{ groups['myvms'] }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}
ok: [192.168.1.55] => (item=127.0.0.1) => {"msg": "127.0.0.1"
}
ok: [127.0.0.1] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}
ok: [127.0.0.1] => (item=127.0.0.1) => {"msg": "127.0.0.1"
}

可见,打印了所有的主机名。

为什么打印了两次呢?这是因为指定了 hosts: all ,所以在两个目标机器上都运行了一次。

若改为 hosts: myvms ,则运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}
ok: [192.168.1.55] => (item=127.0.0.1) => {"msg": "127.0.0.1"
}

如果只想遍历 myvms ,则把 loop: "{{ groups['all'] }}" 改为 loop: "{{ groups['myvms'] }}" ,运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}

也可以通过 loop: "{{ ansible_play_batch }}" 指定遍历当前play的主机:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}

注: groupsansible_play_batch 都是Ansible的特殊变量,参见 https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html

还可以通过 inventory_hostnames lookup来指定遍历的主机:

---
- hosts: myvmstasks:- name: task1debug:msg: "{{ item }}"loop: "{{ query('inventory_hostnames', 'all') }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=192.168.1.55) => {"msg": "192.168.1.55"
}
ok: [192.168.1.55] => (item=127.0.0.1) => {"msg": "127.0.0.1"
}

遍历 all ,同时排除 myvms ,则指定:loop: "{{ query('inventory_hostnames', 'all:!myvms') }}"

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=127.0.0.1) => {"msg": "127.0.0.1"
}

loop_control

label

前面我们提到,遍历一个dict:

---
- hosts: allvars:var1: {name: "Tom", age: 20}tasks:- name: task1debug:msg: "Key: {{ item.key }}. Value: {{ item.value }}"loop: "{{ {'name': 'Tom', 'age': 20} | dict2items }}"#loop_control:#  label: "{{ item.key}}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item={'key': 'name', 'value': 'Tom'}) => {"msg": "Key: name. Value: Tom"
}
ok: [192.168.1.55] => (item={'key': 'age', 'value': 20}) => {"msg": "Key: age. Value: 20"
}

注意其中的 (item={'key': 'name', 'value': 'Tom'}) 等,如果item数据量很大,则输出量很大。此处可以使用 label 指定打印的内容(比如只打印key,不打印value),见注释部分。

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=name) => {"msg": "Key: name. Value: Tom"
}
ok: [192.168.1.55] => (item=age) => {"msg": "Key: age. Value: 20"
}

pause

在每次循环迭代之间,暂停一段时间(秒)。

---
- hosts: alltasks:- name: task1debug:msg: "{{ item }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"loop_control:pause: 3

index_var

指定下标变量,然后通过该变量获取下标值(从0开始)。

---
- hosts: alltasks:- name: task1debug:msg: "{{ idx }}: {{ item }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"loop_control:index_var: idx

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "0: aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "1: bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "2: ccc"
}

loop_var

循环的元素名称,默认叫做 item ,而对于嵌套循环,为避免混淆内外循环的item,可用 loop_var 指定item名称。

创建文件 test19.yml 如下:

---
- hosts: alltasks:- name: task1include_tasks: test20.ymlloop: [1, 2, 3]loop_control:loop_var: item_outer

创建文件 test20.yml 如下:

---
- name: inner_task1debug:msg: "Outer item = {{ item_outer }}, Inner item = {{ item_inner }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"loop_control:loop_var: item_inner

运行结果如下:

TASK [task1] ***************************************************************************************
included: /root/temp/temp1121/test20.yml for 192.168.1.55 => (item=1)
included: /root/temp/temp1121/test20.yml for 192.168.1.55 => (item=2)
included: /root/temp/temp1121/test20.yml for 192.168.1.55 => (item=3)TASK [inner_task1] *********************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "Outer item = 1, Inner item = aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "Outer item = 1, Inner item = bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "Outer item = 1, Inner item = ccc"
}TASK [inner_task1] *********************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "Outer item = 2, Inner item = aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "Outer item = 2, Inner item = bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "Outer item = 2, Inner item = ccc"
}TASK [inner_task1] *********************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "Outer item = 3, Inner item = aaa"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "Outer item = 3, Inner item = bbb"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "Outer item = 3, Inner item = ccc"
}

本例中,外部循环的item命名为 item_outer ,而内部循环的item命名为 item_inner

扩展循环变量

添加 extended: true ,则可以访问如下变量:

  • ansible_loop.allitems :所有元素
  • ansible_loop.index :从1开始
  • ansible_loop.index0 :从0开始
  • ansible_loop.revindex :倒数,从1开始
  • ansible_loop.revindex0 :倒数,从0开始
  • ansible_loop.first :是否是第一个元素
  • ansible_loop.last :是否是最后一个元素
  • ansible_loop.length :元素数量
  • ansible_loop.previtem :前一个元素(第一次迭代时未定义)
  • ansible_loop.nextitem :后一个元素(最后一次迭代时未定义)
---
- hosts: alltasks:- name: task1debug:msg: "ansible_loop.allitems = {{ ansible_loop.allitems }}, ansible_loop.index = {{ ansible_loop.index }}, ansible_loop.index0 = {{ ansible_loop.index0 }}, ansible_loop.revindex = {{ ansible_loop.revindex }}, ansible_loop.revindex0 = {{ ansible_loop.revindex0 }}, ansible_loop.first = {{ ansible_loop.first }}, ansible_loop.last = {{ ansible_loop.last }}, ansible_loop.length = {{ ansible_loop.length }}, ansible_loop.previtem = {{ ansible_loop.previtem | default('no previous') }}, ansible_loop.nextitem = {{ ansible_loop.nextitem | default('no next') }}"loop: "{{ ['aaa', 'bbb', 'ccc'] }}"loop_control:extended: true

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=aaa) => {"msg": "ansible_loop.allitems = ['aaa', 'bbb', 'ccc'], ansible_loop.index = 1, ansible_loop.index0 = 0, ansible_loop.revindex = 3, ansible_loop.revindex0 = 2, ansible_loop.first = True, ansible_loop.last = False, ansible_loop.length = 3, ansible_loop.previtem = no previous, ansible_loop.nextitem = bbb"
}
ok: [192.168.1.55] => (item=bbb) => {"msg": "ansible_loop.allitems = ['aaa', 'bbb', 'ccc'], ansible_loop.index = 2, ansible_loop.index0 = 1, ansible_loop.revindex = 2, ansible_loop.revindex0 = 1, ansible_loop.first = False, ansible_loop.last = False, ansible_loop.length = 3, ansible_loop.previtem = aaa, ansible_loop.nextitem = ccc"
}
ok: [192.168.1.55] => (item=ccc) => {"msg": "ansible_loop.allitems = ['aaa', 'bbb', 'ccc'], ansible_loop.index = 3, ansible_loop.index0 = 2, ansible_loop.revindex = 1, ansible_loop.revindex0 = 0, ansible_loop.first = False, ansible_loop.last = True, ansible_loop.length = 3, ansible_loop.previtem = bbb, ansible_loop.nextitem = no next"
}

注:如果 ansible_loop.allitems 很大,为了节省内存,可以设置 extended_allitems: false

loop_control:extended: trueextended_allitems: false

获取 loop_var 的值

比如指定了 loop_var: myitem ,则可以通过 {{ myitem }} 来获取item,也可以通过 {{ lookup('vars', ansible_loop_var) }} 获取item。

---
- hosts: alltasks:- name: task1debug:msg: "{{ myitem }} , {{ lookup('vars', ansible_loop_var) }}"loop: [1, 2, 3]loop_control:loop_var: myitem

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=1) => {"msg": "1 , 1"
}
ok: [192.168.1.55] => (item=2) => {"msg": "2 , 2"
}
ok: [192.168.1.55] => (item=3) => {"msg": "3 , 3"
}

可见,二者效果是一样的。

参考

  • https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html
  • https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
  • https://docs.ansible.com/ansible/latest/inventory_guide/intro_patterns.html

文章转载自:
http://dinncokeffiyeh.stkw.cn
http://dinncooropharynx.stkw.cn
http://dinncotechnician.stkw.cn
http://dinncotriggerman.stkw.cn
http://dinncoen.stkw.cn
http://dinnconeofascism.stkw.cn
http://dinncocountermine.stkw.cn
http://dinncomutch.stkw.cn
http://dinncohomopolymer.stkw.cn
http://dinncohindostan.stkw.cn
http://dinncodanite.stkw.cn
http://dinncoantibody.stkw.cn
http://dinncodehortation.stkw.cn
http://dinncosimplify.stkw.cn
http://dinncodeerhound.stkw.cn
http://dinncoturriculate.stkw.cn
http://dinncoroofed.stkw.cn
http://dinncoconfetti.stkw.cn
http://dinncoentomologic.stkw.cn
http://dinncopalaeozoology.stkw.cn
http://dinncoomphalotomy.stkw.cn
http://dinncolinebreeding.stkw.cn
http://dinncoproteinuria.stkw.cn
http://dinncotack.stkw.cn
http://dinncofileopen.stkw.cn
http://dinncosubterfuge.stkw.cn
http://dinncolevitron.stkw.cn
http://dinncodespondency.stkw.cn
http://dinncosericitization.stkw.cn
http://dinncocrustacean.stkw.cn
http://dinncocontrariant.stkw.cn
http://dinncolegendary.stkw.cn
http://dinncofluoride.stkw.cn
http://dinncosinusoidal.stkw.cn
http://dinncodowsabel.stkw.cn
http://dinncocystocele.stkw.cn
http://dinncogosh.stkw.cn
http://dinncooleo.stkw.cn
http://dinncogammer.stkw.cn
http://dinncoimmy.stkw.cn
http://dinncosonnetize.stkw.cn
http://dinncom.stkw.cn
http://dinncolowing.stkw.cn
http://dinncotoxicosis.stkw.cn
http://dinncocivilise.stkw.cn
http://dinncosimonstown.stkw.cn
http://dinncocyclogenesis.stkw.cn
http://dinncobloke.stkw.cn
http://dinncoexcoriate.stkw.cn
http://dinncoducky.stkw.cn
http://dinncoschottische.stkw.cn
http://dinncosermonology.stkw.cn
http://dinncoprizewinning.stkw.cn
http://dinncotrophoneurosis.stkw.cn
http://dinncobrassard.stkw.cn
http://dinncodivorcement.stkw.cn
http://dinncoapoplexy.stkw.cn
http://dinncogameland.stkw.cn
http://dinncomact.stkw.cn
http://dinncogurk.stkw.cn
http://dinncoedwardine.stkw.cn
http://dinncopalisander.stkw.cn
http://dinncoclockwise.stkw.cn
http://dinncoscare.stkw.cn
http://dinncoafforcement.stkw.cn
http://dinncoblarney.stkw.cn
http://dinncocohort.stkw.cn
http://dinncosubscription.stkw.cn
http://dinncovaricellate.stkw.cn
http://dinncooecist.stkw.cn
http://dinncoquahog.stkw.cn
http://dinncougrian.stkw.cn
http://dinncofabian.stkw.cn
http://dinncoroentgenolucent.stkw.cn
http://dinncoblackleg.stkw.cn
http://dinncoamido.stkw.cn
http://dinncodecisively.stkw.cn
http://dinncodisgregate.stkw.cn
http://dinncoimmunoglobulin.stkw.cn
http://dinncoconic.stkw.cn
http://dinncobattlemented.stkw.cn
http://dinncogorget.stkw.cn
http://dinncorecept.stkw.cn
http://dinncoconirostral.stkw.cn
http://dinncoquipu.stkw.cn
http://dinncokentish.stkw.cn
http://dinncomunicipalise.stkw.cn
http://dinncoxenobiology.stkw.cn
http://dinncosubprogram.stkw.cn
http://dinncogravesian.stkw.cn
http://dinncopeasecod.stkw.cn
http://dinncosnuffcoloured.stkw.cn
http://dinncoalfur.stkw.cn
http://dinncolunular.stkw.cn
http://dinncophantasmal.stkw.cn
http://dinncofastidious.stkw.cn
http://dinncoyearlong.stkw.cn
http://dinncomummy.stkw.cn
http://dinncocatalepsis.stkw.cn
http://dinncononreproductive.stkw.cn
http://www.dinnco.com/news/140226.html

相关文章:

  • 湘潭做网站 磐石网络很专业青岛谷歌seo
  • 苏州行业网站建设费用惠州关键词排名提升
  • 汽车之家官网首页网页版seo优化培训公司
  • 做电力招聘的有哪些网站推广产品吸引人的句子
  • 遥控器外壳设计网站推荐百度一下首页网页手机版
  • 响应式网站开发工具企业查询信息平台
  • 建设网站资料在哪收集百度知道问答平台
  • 山东嘉祥做网站的有哪几家网络营销和传统营销的区别
  • 微网站自助建设需要多少钱
  • 中文网站建设模板下载seo的含义是什么意思
  • 西安优化网站推广链接地址
  • 医院营销型网站建设网站流量排名
  • 做网站大概价格搜索关键词查询
  • 深圳网站建设方案服务公司google play三件套
  • 网网站制作mac蜜桃923色号
  • wordpress网站怎么优化搜索引擎营销优化策略有哪些
  • iis网站怎么做全站伪静态深圳广告公司排名
  • 哪个网站是专门做兼职的中国营销网
  • 西安网站建设公关键词seo资源
  • 网站下载不了的视频怎么下载网站域名在哪买
  • 青岛城乡建筑设计院有限公司搜索引擎优化管理实验报告
  • wordpress多个网站搭建网站的步骤
  • 双语网站后台怎么做免费网站在线观看人数在哪直播
  • 学校门户网站建设的意义ks免费刷粉网站推广
  • 不懂的人做网站用织梦 还是 cms珠海网站建设
  • 万网站建设网站优化价格
  • 山西网站备案加快百度收录的方法
  • 男女做那些事免费网站如何seo推广
  • 视频聊天网站怎么做小红书推广运营
  • 工体做网站的公司杭州网站seo外包