英文:
Limiting "Changed" output or optimizing playbook output
问题
以下是已翻译的内容:
这里有一些根据某些条件查找文件的代码示例(在此示例中,文件大小大于或等于40k)。
---
- hosts: nodes
become: true
vars_files: my_vars.yml
vars:
where: "/etc"
what: "*.conf"
tasks:
- name: 查找所有大小大于40k的文件
ansible.builtin.find:
paths: "{{where}}"
size: 40k
recurse: yes
register: output
- name: 输出上述结果
ansible.builtin.shell:
"echo {{item.path}} >> testfile3"
loop: "{{output['files']|flatten(1)}}"
现在,这个代码段虽然“成功”运行,但会显示一堆“changed: [host1] => ...”的橙色文本,而且剧本输出是一大堆文本。是否有一种合适的方式来控制和限制输出?或者是否有更好的编写剧本的方法?
英文:
Here's a bit of code for finding files based on some criteria (in this example, files greater >=40k).
---
- hosts: nodes
become: true
vars_files: my_vars.yml
vars:
where: "/etc"
what: "*.conf"
tasks:
- name: Find all files greater than 40k
ansible.builtin.find:
paths: "{{where}}"
size: 40k
recurse: yes
register: output
- name: Output the above
ansible.builtin.shell:
"echo {{item.path}} >> testfile3"
loop: "{{output['files']|flatten(1)}}"
Now, this runs "successfully" but it throws up a bunch of "changed: [host1] => ..." orange text and the playbook output is a wall of text. Is there a proper way of controlling and limit the output? Or is there a better way to code the playbook?
答案1
得分: 2
基于我猜测你的需求(请确保你阅读了如何提问良好问题,特别注意最小可复现示例部分,以备你的下一篇文章),以下内容应该符合你(猜测的)需求:
- name: 查找所有大于40k的文件
ansible.builtin.find:
paths: "{{ where }}"
size: 40k
recurse: yes
register: output
- name: "将上述寄存器的路径写入目标节点的文本文件
(替换以前的输出)"
ansible.builtin.copy:
content: "{{ output.files | map(attribute='path') | join('\n') }}"
dest: /path/to/testfile3
- name: 如果你只想要输出,只需调试列表
ansible.builtin.debug:
var: output.files | map(attribute='path')
为了进一步解决你帖子中提出的一些问题:
- 当已经有一个模块可以完成你期望的工作时,你不应该使用
ansible.builtin.shell
。 - 如果你仍然需要使用
ansible.builtin.shell
,就像 @4snok 已经提出的,它默认不是幂等的。你将需要自己管理幂等性。请参阅定义变更。 - 你原始playbook中的基本问题是(我猜测)
loop
的输出(在这里绝对不需要)。如果出于某种原因你最终的代码仍然需要一个循环,有几种方法可以限制其输出:- 从一开始就限制你在循环中使用的信息,以便只在循环中具有所需的数据。例如:
- name: 在注册结果中循环文件路径 ansible.builtin.debug: var: item loop: "{{ output.files | map(attribute='path') }}"
- 在每个循环中限制输出以仅保留你想要保留的内容。请参阅使用
label
限制循环输出以获取更多信息。例如:- name: 限制循环输出 ansible.builtin.debug: msg: "文件{{ item.path }}的校验和为{{ item.checksum }}" loop: "{{ output.files }}" loop_control: label: "{{ item.path }}"
- 从一开始就限制你在循环中使用的信息,以便只在循环中具有所需的数据。例如:
英文:
Based on what I guess you're looking for (please make sure you read How to ask a gook question paying a special attention to the Minimal reproducible example section for your next post), the following should approach your (guessed) requirement:
- name: Find all files greater than 40k
ansible.builtin.find:
paths: "{{where}}"
size: 40k
recurse: yes
register: output
- name: "Print the paths to a text file on the target node
(replacing previous output) from the above register"
ansible.builtin.copy:
content: "{{ output.files | map(attribute='path') | join('\n') }}"
dest: /path/to/testfile3
- name: If you're only looking for an output, just debug the list
ansible..builtin.debug:
var: output.files | map(attribute='path')
To go a bit further and address a few concerns raised in your post:
- You should not use
ansible.builtin.shell
when there's a module already doing the job you expect. - If you still need to use
ansible.builtin.shell
, as already raised by @4snok, it is not idempotent by default. You will have to manage idempotency yourself. See Defining changed - The base problem in your original playbook is (I guess) the output of
loop
(which is definitely not needed here). If for some reason you still need a loop in your final code, there are several ways to limit its output:- Limit the information your are looping on from start so that you only have the needed data in the loop. As an example:
- name: Loop on files path in registered result ansible.builtin.debug: var: item loop: "{{ output.files | map(attribute='path') }}"
- Limit the ouput in each loop to only what you want to keep. See Limiting loop ouput with
label
for more information. Example:- name: Limit loop output ansible.builtin.debug: msg: "Checksum of {{ item.path }} is {{ item.checksum }}" loop: "{{ output.files }}" loop_control: label: "{{ item.path }}"
- Limit the information your are looping on from start so that you only have the needed data in the loop. As an example:
答案2
得分: 1
任务:
- 名称: 查找所有大于40k的文件
ansible.builtin.find:
paths: "{{where}}"
size: 40k
recurse: yes
注册: 输出
no_log: true
- 名称: 输出上述内容
ansible.builtin.shell:
"echo {{item.path}} >> testfile3"
循环: "{{output['files']|flatten(1)}}"
changed_when: false
英文:
The shell module isn't idempotent. When performing it multiple times doesn't necessarily produce the same result every time it is performed. In your case the content of testfile3 file will be changed every time you run the playbook.
You can control this behavior with changed_when
option.
To suppress output from the task use 'no_log: true'.
tasks:
- name: Find all files greater than 40k
ansible.builtin.find:
paths: "{{where}}"
size: 40k
recurse: yes
register: output
no_log: true
- name: Output the above
ansible.builtin.shell:
"echo {{item.path}} >> testfile3"
loop: "{{output['files']|flatten(1)}}"
changed_when: false
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论