运维必备 | ansible 自动化运维工具之循环内置关键字使用示例

2023-10-31 18:18:41 浏览数 (1)

0x00 ansible 循环

描述: 在Ansible中,循环是一种重复执行任务或操作的方法, 循环允许您对一组数据、主机列表或其他可迭代对象执行相同的操作,即循环使得在Ansible中执行重复任务变得更加简单和高效,减少了重复代码的编写,提高了任务的可维护性和可读性。

在实际使用ansible的过程中,我们经常需要处理一些返回信息而这些返回信息中,通常可能不是单独的一条返回信息而是一个信息列表,此时你将会用到循环。

「循环常用关键字:」

  • with_items : 迭代列表里面的值或者变量的结果,不分层次全部输出
  • with_list : 循环的输出列表(最外层大列表)中的每一项,分层次
  • with_flattened : 与items相同将嵌套列表"拉平展开",循环的处理每个元素
  • with_together : 将两个列表中的元素"对齐合并-一一对应
  • with_cartesian : 将每个小列表中的元素按照"笛卡尔的方式"组合后,循环的处理每个组合
  • with_nested : 与cartesian相同将每个小列表中的元素按照"笛卡尔的方式"组合
  • with_indexed_items : 根据列表设置索引值,可根据索引值取值
  • with_sequence : 迭代序列选择步长和输出指定格式话
  • with_random_choice : 列表中随机返回一个值
  • with_dict : 遍历字典key与value
  • with_subelements : 遍历复合结构的字典属性
  • with_file : 读取ansible主机中的文件中内容并且遍历
  • with_fileglob : 读取ansible主机中指定的目录中匹配符合模式的文件名,只包括文件不包括目录;

with_items 关键字

描述: 如果我们想要循环的处理信息列表中的每一条信息,此时我们该怎么办呢?

答案就是with_items关键字, 它是指定遍历的变量和item变量进行迭代输出; 即"with_items"关键字会把返回的列表信息自动处理,将每一条信息单独放在一个名为"item"的变量中,我们只要获取到名为"item"变量的变量值,即可循环的获取到列表中的每一条信息。

代码语言:javascript复制
# 语法1:
  tasks:
  - debug:
      msg: "{{item}}"
    with_items: [ 1, 2, 3 ]

# 语法2:
  tasks:
  - debug:
      msg: "{{item}}"
    with_items: [ 1, 2, 3 ]

# 语法3:
 tasks:
  - debug:
      msg: "{{item.test1}}" #"a"和"c"会被输出。
    with_items:
    - { test1: a, test2: b }
    - { test1: c, test2: d } 

# 语法4:jinja2是一种模板语言,jinja2是一个基于python的模板引擎
- debug:
    msg:
      "{% for i in item %}
        {{ i }}
      {% endfor %}"
    with_items : [ 1, 2, 3 ]

例如,如果我想要获取到清单中所有分组的主机的主机名,并且获取返回信息中的第二条信息;

代码语言:javascript复制
ansible testA -m debug -a "msg={{groups.all}}"
# 10.10.107.221 | SUCCESS => {
#     "msg": [
#         "local",
#         "10.10.107.221",
#         "10.20.172.179"
#     ]
# }

# 获取第二项
ansible testA -m debug -a "msg={{groups.all[1]}}"
# 10.10.107.221 | SUCCESS => {
#     "msg": "10.10.107.221"
# }

偷偷的告诉你哟?极客全栈修炼】微信小程序已开放

可直接在微信里面直接浏览博主文章哟,后续将上线更多有趣的小工具。


「示例演示:」

  • 示例1.使用 with_items 关键字传入需要遍历的数据。
代码语言:javascript复制
# cat > withitems.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_items: "{{groups.all}}"
  - debug:
      msg: "{% for i in item %}{{ i }}{% endfor %}"
    with_items : ["1","2","3"]  #注意需要是字符串类型
END

执行结果:

代码语言:javascript复制
$ ansible-playbook withitems.yml

TASK [debug]  #返回信息中的每一条信息都会循环的被debug模块处理 (一条执行一次)
ok: [local] => (item=local) => {
    "msg": "local"
}
ok: [local] => (item=10.10.107.221) => {
    "msg": "10.10.107.221"
}
ok: [local] => (item=10.20.172.179) => {
    "msg": "10.20.172.179"
}

#jinja2语言循环语法
TASK [debug] 
ok: [local] => (item=1) => {
    "msg": "1"
}
ok: [local] => (item=2) => {
    "msg": "2"
}
ok: [local] => (item=3) => {
    "msg": "3"
}
  • 示例2,在没有学会使用循环之前如果想要在同一主机中创建四个文件,但是学了循环后您只需要将建立的文件放入数组之中,然后迭代使用,循环常使用案例:
代码语言:javascript复制
# cat > items1.yml <<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  vars:
    dirs:
    - "/tmp/a"
    - "/tmp/b"
    - "/tmp/c"
    - "/tmp/d"
  tasks:
  - file:
      path: "{{item}}"    #关键点1 (多次运行file模块 - 每一行运行一次)
      state: touch
    with_items: "{{dirs}}"  #重复的操作越多,使用循环则越方便  #关键点2
  - shell: "whoami"     
    register: "cmd"
  - debug:
      msg: "{{cmd[item]}}"   #关键点3  shell模块命令遍历返回的信息
    with_items: "{{cmd}}"    #关键点4
  - debug:
      var: cmd[item]   #关键点3  shell模块命令遍历返回的信息
    with_items: "{{cmd}}"    #关键点4
END

执行结果:

代码语言:javascript复制
$ ansible-playbook items1.yml

# 循环建立文件
TASK [file]
changed: [local] => (item=/tmp/a)
changed: [local] => (item=/tmp/b)
changed: [local] => (item=/tmp/c)
changed: [local] => (item=/tmp/d)

# 循环出来命令执行结果
TASK [debug]
ok: [local] => (item=changed) => {
    "msg": true
}
ok: [local] => (item=stdout) => {
    "msg": "root"
}
ok: [local] => (item=delta) => {
    "msg": "0:00:00.022253"
}
ok: [local] => (item=stdout_lines) => {
    "msg": ["root"]
}
ok: [local] => (item=end) => {
    "msg": "2019-08-01 10:47:41.760052"
}
ok: [local] => (item=start) => {
    "msg": "2019-08-01 10:47:41.737799"
}
ok: [local] => (item=cmd) => {
    "msg": "whoami"
}
ok: [local] => (item=failed) => {
    "msg": false
}

# debug vars执行返回的变量(有格式输出)
ok: [local] => (item=changed) => {
    "ansible_loop_var": "item",
    "cmd[item]": true,
    "item": "changed"
}
ok: [local] => (item=stdout) => {
    "ansible_loop_var": "item",
    "cmd[item]": "root",
    "item": "stdout"
}
....... 其他忽略
  • 示例3.采用循环我们也可以像file模块一样执行多个命令,只需要将要执行的命令放入with_items关键字中, 循环输出方式:
代码语言:javascript复制
# cat > items2.yml <<END
---
- hosts: local
  remote_user: root
  vars:
    cmd:   #关键点
      - "hostname"
      - "hostname -I"
  gather_facts: no
  tasks:
  - name: "Mutil Shell Execute"
    shell: "{{item}}"      #关键点
    with_items: "{{cmd}}"
    register: returncmd  #会把多次执行的结果放入returncmd变量之中
  - debug:
      var: returncmd
#当使用了循环以后,每次shell模块执行后的返回值都会放入一个名为"results"的序列中,我们可以直接调用使用
  - name: "show shell execute result"
    debug:
      msg: "{{item.stdout}}"   #关键点
    with_items: "{{returncmd.results}}"   #关键点
#因为debug模块只是输出了经过jinja2的for循环处理过的信息而已,debug模块并没有因为for循环而被重复的调用
  - name: "jinja2 syntax"
    debug:
      msg: "{% for i in returncmd.results %} {{ i.stdout }} {% endfor %}" #for循环的语法为jinja2语言中的for循环语法
END

执行结果:

代码语言:javascript复制
$ ansible-playbook items2.yml

TASK [show shell execute result]
ok: [local] => (item={'stderr_lines': [], .... , 'stdout_lines': [u'master'], u'start': u'2019-08-01 11:17:55.900489'}) => {   
   "msg": "master"
}
ok: [local] => (item={'stderr_lines': [], ..... , 'stdout_lines': [u'10.10.107.222 192.168.1.99 '], u'start': u'2019-08-01 11:17:56.116440'}) => {
    "msg": "10.10.107.222 192.168.1.99 "
}

# inja2 语法更加的精简
TASK [jinja2 syntax]
ok: [local] => {
    "msg": " master  10.10.107.222 192.168.1.99  "
}

weiyigeek.top-returncmd

with_list 关键字

描述: 前面我们说 with_items 会循环的输出列表(最外层大列表)中的每一项,按照之前的思路debug模块应该会将每个小列表作为一个小整体输出,而不应该输出小列表中的每个元素,但是事实却是 with_items 将嵌套在大列表中的每个小列表都展开了,并且将小列表中的元素都输出了.

「Q: 如果我们想要将每个小列表作为一个整体输出该怎么办呢?」

❝答: 那就需要我们的主人公 with_list 关键字,可以将每个小列表作为一个整体输出;经过with_list处理后,每个嵌套在大列表中的小列表都被当做一个整体存放在item变量中,最终被debug作为一个小整体输出了,而不会像with_items一样将小列表"展开拉平"后一并将小列表中的元素循环输出。 ❞

「with_list 语法示例」:

代码语言:javascript复制
#语法1:
  with_list:
  - [ 1, 2, 3 ]
  - [ a, b ]

#语法2:
  with_list:
    -
      - 1
      - 2
      - 3
    -
      - a
      - b

「示例演示:」

示例1.with_list 关键字 与 with_itemswith_flattened 关键字区别:

代码语言:javascript复制
# cat > itemsVSlist.yml <<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - name: " with_list show"
    debug:
      msg: "{{item}}"
    with_list:    #关键点
    - [ 1, 2]
    - [ a, b ]
  - name: " with_items show"
    debug:
      msg: "{{item}}" 
    with_items: #关键点
    - [ 1, 2 ]
    - [ a, b ]
  - name: " with_flattened show"
    debug:
      msg: "{{item}}"
    with_flattened: #关键点
    - [ 1, 2 ]
    - [ a, b ]
END

执行结果:

代码语言:javascript复制
TASK [with_list show]  #以列表为单位输出
# ok: [local] => (item=[1, 2]) => {
#     "msg": [
#         1,
#         2
#     ]
# }
# ok: [local] => (item=[u'a', u'b']) => {
#     "msg": [
#         "a",
#         "b"
#     ]
# }

TASK [with_items show / with_flattened show]   #会将元素单独输出
# ok: [local] => (item=1) => {
#     "msg": 1
# }
# ok: [local] => (item=2) => {
#     "msg": 2
# }
# ok: [local] => (item=a) => {
#     "msg": "a"
# }
# ok: [local] => (item=b) => {
#     "msg": "b"
# }

「总结说明」:当处理单层的简单列表时 with_listwith_items 以及没有任何区别,with_flattened 只有在处理"嵌套列表"时才会体现出区别;

  • with_items : 会将嵌套在内的小列表"拉平",拉平后循环处理所有元素
  • with_list : 则不会"拉平"嵌套的列表,只会循环的处理列表(最外层列表)中的每一项。
  • with_flattened 与 with_items 效果完全相同,将嵌套列表"拉平展开",循环的处理每个元素

with_together 关键字

描述:目前为止我们了解了三个关键字可以用于循环操作,它们是with_list、with_items、with_flattened,下面引出一个新的关键字 with_together 将两个列表中的元素"对齐合并-一一对应".

「示例演示:」

示例1.在playbook 脚本中 with_together 关键字循环使用示例。

代码语言:javascript复制
# cat > withtogether.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_together:
    - [ 1, 2, 3 ]
    - [ a, b ]
END

#执行结果
# ok: [local] => (item=[1, u'a']) => {
#     "msg": [
#         1,
#         "a"
#     ]
# }
# ok: [local] => (item=[2, u'b']) => {
#     "msg": [
#         2,
#         "b"
#     ]
# }
# ok: [local] => (item=[3, u'c']) => {
#     "msg": [
#         3,
#         "c"
#     ]
# }

结果浅析:

  • 第一个小列表中的第1个值与第二个小列表中的第1个值合并在一起输出了
  • 第一个小列表中的第2个值与第二个小列表中的第2个值合并在一起输出了
  • 第一个小列表中的第3个值与第二个小列表中的第3个值合并在一起输出了
  • 如果元素数量不同的小列表使用with_together对齐合并,不存在列表中对应值将变成NULL
代码语言:javascript复制
ok: [local] => (item=[None, u'c']) => {
    "msg": [
        null,   #列表元素数量不同 [1,2] [a, b, c]
        "c"
    ]
}

ok: [local] => (item=[3, None]) => {
    "msg": [
        3,
        null   #列表元素数量不同 [1,2,3] [a, b]
    ]

with_cartesian 关键字

描述:"with_cartesian"关键字的作用就是将每个小列表中的元素按照"笛卡尔的方式"组合后,循环的处理每个组合;其实还有一个关键字可以代替"with_cartesian",它就是"with_nested"与"with_cartesian"的效果一致;

比如:我们要再{a,b,c}目录下分别建立下面两个目录{test1, test2},常规的用法可以采用# mkdir -p {a,b,c}/{test1,test2}命令,再ansible采用shell模块执行:# ansible test70 -m shell -a "mkdir -p /testdir/testdir/{a,b,c}/{test1,test2}"

但我们这里需要采用with_cartesian关键来实现上述效果:

weiyigeek.top-with_cartesian关键图

「实际案例」:

代码语言:javascript复制
# cat > with_cartesian.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - name: "Show Create directory"
    debug:
      msg: "{{ item }}"
    with_cartesian:   #关键点
    - [a, b, c]
    - [test1, test2]
  - name: "shell create Directory"
    file:
      path: "/tmp/{{item.0}}/{{item.1}}"  #关键点
      state: directory
    with_cartesian:
    - [a, b, c]
    - [test1, test2]
END

「执行结果」

代码语言:javascript复制
#Debug msg情况 -> 笛卡尔积
TASK [Show Create directory] 
ok: [local] => (item=[u'a', u'test1']) => {"msg": ["a","test1"]}
ok: [local] => (item=[u'a', u'test2']) => {"msg": ["a", "test2"]}
ok: [local] => (item=[u'b', u'test1']) => {"msg": ["b","test1"]}
ok: [local] => (item=[u'b', u'test2']) => {"msg": ["b","test2"]}
ok: [local] => (item=[u'c', u'test1']) => {"msg": ["c","test1"]}
ok: [local] => (item=[u'c', u'test2']) => {"msg": ["c","test2"]}

#创建的目录情况
TASK [shell create Directory] 
ok: [local] => (item=[u'a', u'test1'])
ok: [local] => (item=[u'a', u'test2'])
ok: [local] => (item=[u'b', u'test1'])
ok: [local] => (item=[u'b', u'test2'])
ok: [local] => (item=[u'c', u'test1'])
ok: [local] => (item=[u'c', u'test2'])

with_indexed_items 关键字

描述:顾名思义应该与"索引"有关,"with_indexed_items"的作用就是在循环处理列表时为列表中的每一项添加"数字索引","索引"从0开始.

  • 单层列表 :按照顺序进行从0开始编号
  • 多层列表 :会将嵌套的两层列表"拉平"后按照顺序为每一项编号,"拉平"效果跟之前总结的"with_flattened"效果类似;
    • 但是当多加了一层嵌套以后"with_indexed_items"并不能像"with_flattened"一样将嵌套的列表"完全拉平",第二层列表中的项如果仍然是一个列表"with_indexed_items"则不会拉平这个列表,而是将其当做一个整体进行编号

「基础案例:」

示例1.单层列表与多层列表

代码语言:javascript复制
# cat > with_indexed_items.yml <<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - name: "Example play 1"
    debug:
      msg: "E.g 1: index is : {{ item.0 }} , value is {{ item.1 }}"
    with_indexed_items:  #将添加过编号的每一项放入到了item中,简单的单层列表
    - test1  #test1索引编号是0
    - test2  #test2索引编号是1
    - test3  #test3索引编号是2
  - name: "Example play 2"
    debug:
      msg: "E.g 2: index is : {{ item.0 }} , value is {{ item.1 }}"
    with_indexed_items:  #多层列表与with_flattened效果类似进行拉升
    - [a,b,c]
    - [test1, test2]
  - name: "Example play 3"
    debug:
      msg: "E.g 3: index is : {{ item.0 }} , value is {{ item.1 }}"
    with_indexed_items: #多层列表但是列表中镶嵌列表 (特殊重点)
    - [a,b]
    - [c, [d,e]]
    - [end]
END

执行结果:

代码语言:javascript复制
#TASK [Example play 1] 
ok: [local] => (item=[0, u'test1']) => {"msg": "E.g 1: index is : 0 , value is test1"}
ok: [local] => (item=[1, u'test2']) => {"msg": "E.g 1: index is : 1 , value is test2"}
ok: [local] => (item=[2, u'test3']) => {"msg": "E.g 1: index is : 2 , value is test3"}


#TASK [Example play 2] 
ok: [local] => (item=[0, u'a']) => {"msg": "E.g 2: index is : 0 , value is a"
ok: [local] => (item=[1, u'b']) => {"msg": "E.g 2: index is : 1 , value is b"}
ok: [local] => (item=[2, u'c']) => {"msg": "E.g 2: index is : 2 , value is c"}
ok: [local] => (item=[3, u'test1']) => {"msg": "E.g 2: index is : 3 , value is test1"}
ok: [local] => (item=[4, u'test2']) => {"msg": "E.g 2: index is : 4 , value is test2"}


#TASK [Example play 3] 
ok: [local] => (item=[0, u'a']) => {"msg": "E.g 3: index is : 0 , value is a"}
ok: [local] => (item=[1, u'b']) => {"msg": "E.g 3: index is : 1 , value is b"}
ok: [local] => (item=[2, u'c']) => {"msg": "E.g 3: index is : 2 , value is c"}
ok: [local] => (item=[3, [u'd', u'e']]) => {"msg": "E.g 3: index is : 3 , value is [u'd', u'e']"}
ok: [local] => (item=[4, u'end']) => {"msg": "E.g 3: index is : 4 , value is end"}

with_sequence 关键字

描述:采用with_sequence关键字,可以指定开始与结束并且可以指定step步跳,即可以帮助我们按照顺序生成数字序列;"with_sequence"还有一个小功能,就是"格式化"输出数据的功能,"格式化数据"的方法与C语言的printf函数的使用方法类似,

「基础案例:」

代码语言:javascript复制
# cat >with_sequence.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - name: "Method 1"
    debug:
      msg: "{{ item }}"
    with_sequence: start=1 end=3 stride=1
    #其中start=1表示从1开始,end=3表示到5结束,stride=1表示步长为1,即从1到5每次增加1
  - name: "Method 2"
    debug:
      msg: "{{ item }}"
    with_sequence: count=3
    #count=5表示数字序列默认从1开始,到3结束,默认步长为1,与上述两种写法的效果相同
  - name: "Demo 3"
    debug: 
      msg: "{{ item }}"  #" %0.2f"表示将数字格式化为一个保留两位小数点的浮点数
    with_sequence: start=6 end=2 stride=-2 format="number is %0.2f"   #关键点
  - name: "Demo 4 - Create dir"
    file:
      path: "/tmp/test{{ item }}"
      state: directory
    with_sequence:
      start=2
      end=10
      stride=2
END

执行结果:

代码语言:javascript复制
#TASK [Method 1 / Method 1]
ok: [local] => (item=1) => {"msg": "1"}
ok: [local] => (item=2) => {"msg": "2"}
ok: [local] => (item=3) => {"msg": "3"}

#TASK [Demo 3] 
ok: [local] => (item=number is 6.00) => {"msg": "number is 6.00"}
ok: [local] => (item=number is 4.00) => {"msg": "number is 4.00"}
ok: [local] => (item=number is 2.00) => {"msg": "number is 2.00"}

#TASK [Demo 4 - Create dir]
changed: [local] => (item=2)
changed: [local] => (item=4)
changed: [local] => (item=6)
changed: [local] => (item=8)
changed: [local] => (item=10)

总结:

  • 当我们不指定stride的值时,stride的值默认为1;
  • 当end的值小于start的值时,则必须指定stride的值,而且stride的值必须是负数;

with_random_choice 关键字

描述:可以从列表的多个值中随机返回一个值,此时我们可以使用"with_random_choice"关键字来进行处理。

「基础案例:」

示例1.每次返回的结果是从列表中随机选中的一个。

代码语言:javascript复制
# cat >with_random_choice.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_random_choice:
    - "one"
    - 2
    - "three"
    - 4
    - "five"
END

#执行结果(随机列表)
TASK [debug]
ok: [local] => (item=three) => {
    "msg": "three"
}

with_dict 关键字

描述:从字面意思就可看出,它是可以遍历对象的即字典类型的,分别将字典的key与value进行存储并且支持迭代;

「基础案例:」

代码语言:javascript复制
# cat >with_dict.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  vars:
    users:
      WeiyiGeek: female
      Baby_ang: male
  tasks:
  - name: "Demo 1.dict"
    debug:
      msg: "Username: {{ item.key }} , User's gender: {{ item.value }}"
    with_dict: "{{users}}"
  - name: "Demo 2.dict"
    debug:  #关键点
      msg: "Item: {{ item.key }}, Username: {{ item.value['name'] }} , User's gender: {{ item.value.gender }} , User's Telephone: {{ item.value.telephone }}"
    with_dict:
      alice:
        name: Alice Appleworth
        gender: female
        telephone: 123-456-7890
      bob:
        name: Bob Bananarama
        gender: male
        telephone: 987-654-3210
END

执行结果:

代码语言:javascript复制
#TASK [Demo 1.dict] 
ok: [local] => (item={'value': u'male', 'key': u'Baby_ang'}) => {
    "msg": "Username: Baby_ang , User's gender: male"
}
ok: [local] => (item={'value': u'female', 'key': u'WeiyiGeek'}) => {
    "msg": "Username: WeiyiGeek , User's gender: female"
}

#TASK [Demo 2.dict]
ok: [local] => (item={'value': {u'gender': u'male', u'name': u'Bob Bananarama', u'telephone': u'987-654-3210'}, 'key': u'bob'}) => {
    "msg": "Item: bob, Username: Bob Bananarama , User's gender: male , User's Telephone: 987-654-3210"
}
ok: [local] => (item={'value': {u'gender': u'female', u'name': u'Alice Appleworth', u'telephone': u'123-456-7890'}, 'key': u'alice'}) => {
    "msg": "Item: alice, Username: Alice Appleworth , User's gender: female , User's Telephone: 123-456-7890"
}

with_subelements 关键字

描述:该关键字支持复合类型的字典;"with_subelements"的以处理一个的复合结构的字典数据,在处理这个字典的同时,需要指定一个子元素,这个子元素的值必须是一个列表,"with_subelements"会将子元素的列表中的每一项作为一个整体,将其他子元素作为一个整体,然后将两个整体组合成item。

「基础案例:」

示例1.由于item由两个整体组成,所以我们通过item.0获取到第一个小整体,即gender和name属性,然后通过item.1获取到第二个小整体,即hobby列表中的每一项;

代码语言:javascript复制
# cat >with_subelement.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  vars:
    users:
    - name: WeiyiGeek
      gender: male
      hobby:
        - Skateboard
        - VideoGame
    - name: Xiaodaigua
      gender: female
      hobby:
        - Music
  tasks:
  - debug:
      msg: "{{ item.0.name }} 's hobby is {{ item.1 }} , User's Gender is {{ item.0.gender}}"  #关键点(变成子对象元素,既可以分别可以将两个字典进行整合)
    with_subelements:
    - "{{users}}"
    - hobby  #关键点,整合后实际是vars中 {{item}}.hobby
END

执行结果:

代码语言:javascript复制
#TASK [debug] 
ok: [local] => (item=[{u'gender': u'male', u'name': u'WeiyiGeek'}, u'Skateboard']) => {
    "msg": "WeiyiGeek 's hobby is Skateboard , User's Gender is male"
}
ok: [local] => (item=[{u'gender': u'male', u'name': u'WeiyiGeek'}, u'VideoGame']) => {
    "msg": "WeiyiGeek 's hobby is VideoGame , User's Gender is male"
}
ok: [local] => (item=[{u'gender': u'female', u'name': u'Xiaodaigua'}, u'Music']) => {
    "msg": "Xiaodaigua 's hobby is Music , User's Gender is female"
}

with_file 关键字

描述:循环的获取到ansible主机中的文件的内容,注意不是远程目标主机中的文件;

「基础案例:」

代码语言:javascript复制
# cat > with_file.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_file:  #可以通过"with_file"关键字获取到ansible主机中的文件内容
    - /tmp/demo1.txt  #ansbile主机上的文件
    - /tmp/demo2.txt
END

执行结果:

代码语言:javascript复制
#TASK [debug]
ok: [local] => (item=.....) => {
    "msg": "mastern10.10.107.222 192.168.1.99 nMon Aug  5 16:29:39 CST 2019"
}
ok: [local] => (item=.....) => {
    "msg": "Linux master 3.10.0-957.12.2.el7.x86_64 #1 SMP Tue May 14 21:24:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux"
}

with_fileglob 关键字

描述: 是用来匹配文件名称的,我们可以通过"with_fileglob"关键字,在指定的目录中匹配符合模式的文件名;注意: "with_fileglob"只会匹配指定目录中的文件,而不会匹配指定目录中的目录。

比如: 我们定义了一个列表,这个列表中只有一个值是一个路径,路径中包含一个通配符,如"/testdir/*"应该代表了/testdir目录中的所有文件, 当前常用通配符有*、?

「基础案例:」

代码语言:javascript复制
# cat >with_fileglob.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_fileglob:  #可以通过"with_file"关键字获取到ansible主机中的文件内容
    - /tmp/demo*.???  #ansbile主机上的文件
    - /root/*
END

执行结果:

代码语言:javascript复制
#TASK [debug] 
ok: [local] => (item=/tmp/demo1.txt) => {"msg": "/tmp/demo1.txt"}
ok: [local] => (item=/tmp/demo2.txt) => {"msg": "/tmp/demo2.txt"}
ok: [local] => (item=/root/with_dict.yml) => {"msg": "/root/with_dict.yml"}
ok: [local] => (item=/root/with_subelement.yml) => {"msg": "/root/with_subelement.yml"}
ok: [local] => (item=/root/with_fileglob.yml) => {"msg": "/root/with_fileglob.yml"}
ok: [local] => (item=/root/with_sequence.yml) => {"msg": "/root/with_sequence.yml"}
ok: [local] => (item=/root/with_random_choice.yml) => {"msg": "/root/with_random_choice.yml"}
ok: [local] => (item=/root/with_file.yml) => {"msg": "/root/with_file.yml"}

执行上面的playbook后,会将满足通配符的文件都会被匹配到最终循环的被debug模块输出;

本文至此完毕,更多技术文章,尽情等待下篇好文!

原文地址: https://cloud.tencent.com/developer/article/2128568

0 人点赞