我希望能够确定多个主机上特定目录列表的平均大小。我首先在主机上找到我想要的目录,评估它们的大小,并将结果放入一个漂亮的字典中:
- name: find log dirs
shell: "find / -type d -name 'log' 2>/dev/null | sort"
register: log_list
- name: evaluate dir sizes
shell: "du -sk {{ item }} | awk '{ print $1 }'"
register: folder_size
loop : "{{ log_list.stdout_lines }}"
- name: build dict
set_fact:
folder_info: "{{ folder_info|default({}) | combine({item.item: {'path': item.item, 'size': item.stdout|int}}) }}"
loop: "{{ folder_size.results }}"
回到Ansible控制器,我把所有这些字典放在一起,在一个漂亮的大字典,也把dirs列表:
- name: gather folder info
set_fact:
all_dirs: "{{ all_dirs|default([]) + hostvars[item].dir_list|unique }}"
all_folder_info: "{{ all_folder_info|default({}) | combine({hostvars[item].inventory_hostname:hostvars[item].folder_info}) }}"
loop: "{{ groups['backoffice'] }}"
调试all_folder_info会得到如下结果:
TASK [debug] *******************************************************************
ok: [localhost] => {
"all_folder_info": {
"some.host.com": {
"/some/directory/": {
"path": "/some/directory",
"size": 220
},
"/some/other/directory": {
"path": "/some/other/directory",
"size": 8
},
"/some/third/directory": {
"path": "/some/third/directory",
"size": 319404
}
},
我现在需要遍历这个巨大的字典来提取我想要的信息并对其进行数学运算,但我被卡住了。我试着像这样压缩,Ansible说不能模板:
- name: debug
debug:
var: (all_folder_info[item.0].[item.1].size | sum) / (all_folder_info[item.0].[item.1].size | length)
loop: "{{ groups['backoffice']|zip_longest(all_dirs|unique)|list }}"
这似乎充其量只是将两个列表放入键:值对中。我做错了什么?
为了避免需要进行嵌套循环,我们可以使用过滤器来获取单个主机所需的值。这段代码应该可以满足您的需求。
- debug:
msg: "{{ item }} average size: {{ all_folder_info[item].values() | map(attribute='size') | sum / all_folder_info[item] | length }}"
loop: "{{ groups['backoffice'] }}"
分解:
all_folder_info['some.host.com']
现在是一个字典,但我更喜欢一个只有值的列表,以便我可以使用map
过滤器来操作它。我发现你可以做.values()
来返回一个没有键的值列表——all_folder_info['some.host.com'].values()
:
[
{"path": "/some/directory", "size": 220},
{"path": "/some/other/directory", "size": 8},
{"path": "/some/third/directory", "size": 319404}
]
然后对其应用map
过滤器以提取size
属性—all_folder_info['some.host.com'].values() | map(attribute='size') | list
:
[220, 8, 319404]
由于列表只包含整数,因此我们可以使用sum
过滤器对列表的总数求和。