限制“Changed”输出或优化playbook输出。

huangapple go评论178阅读模式
英文:

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')

为了进一步解决你帖子中提出的一些问题:

  1. 当已经有一个模块可以完成你期望的工作时,你不应该使用 ansible.builtin.shell
  2. 如果你仍然需要使用 ansible.builtin.shell,就像 @4snok 已经提出的,它默认不是幂等的。你将需要自己管理幂等性。请参阅定义变更
  3. 你原始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:

  1. You should not use ansible.builtin.shell when there's a module already doing the job you expect.
  2. 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
  3. 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 }}"
      

答案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

huangapple
  • 本文由 发表于 2023年6月26日 07:22:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552780.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定