将所有主机的输出复制到一个单独的txt文件中,使用Ansible。

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

Copy outputs from all hosts into a single txt file with Ansible

问题

以下是翻译好的内容:

以下代码似乎会覆盖之前的输出,因为我只得到最后一个主机的输出。
我期望所有输出都在一个文件中,就像屏幕上的标准输出一样。

```yaml
  tasks:
    - ios_command:
       commands:
         - sh run | i hostname
         - show vlan brief | i active
      register: output
    - debug: 
        msg="{{ output.stdout_lines }}"
    - copy:
        content: "{{ output.stdout_lines }}"
        dest: /etc/ansible/show01.txt

结果缺少了 s1、s2 和 s3:

[["hostname s4"], 
["1   default                     active    ", 
"10   VLAN0010                    active    ",
"100  VLAN0100                    active    Gi0/0"]]

在Python中(使用nornir、netmiko或scrapli),很容易告诉copyopen()命令追加'a'的结果,而不是覆盖'w',然后它将“添加”行到txt文件中,而不是覆盖它。

with open('output_june.txt', 'a') as file3:

如何在Ansible中实现这一点?

英文:

The following code seems to overwrite the previous output as I get only the last host's output in there.
I'm expecting all outputs together in one file. Just like the stdout on screen.

  tasks:
    - ios_command:
       commands:
         - sh run | i hostname
         - show vlan brief | i active
      register: output
    - debug: 
        msg="{{ output.stdout_lines }}"
    - copy:
        content: "{{ output.stdout_lines }}"
        dest: /etc/ansible/show01.txt

The result is missing s1, s2, and s3:

[["hostname s4"], 
["1   default                     active    ", 
"10   VLAN0010                    active    ",
"100  VLAN0100                    active    Gi0/0"]]

In Python (with nornir, netmiko, or scrapli), it's easy to tell the copy or open() command to append 'a' the result, not to write 'w' it, then it will "add" lines into the txt file, not overwrite it.

with open('output_june.txt', 'a') as file3:

How to do this in Ansible?

答案1

得分: 1

将所有记录在一个单一任务中写入文件。这更有效率,可以避免并行写入同一文件时可能出现的竞争条件。例如,在下面的示例中,在变量out中注册命令的输出,并在单一debug中显示记录。

shell> cat pb.yml
- hosts: all

  tasks:

    - shell: "date; uname -smr"
      register: out

    - debug:
        msg: |
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true

结果是

shell> ansible-playbook pb.yml

PLAY [all] ************************************************************************************

TASK [shell] **********************************************************************************
changed: [s1]
changed: [s2]

TASK [debug] **********************************************************************************
ok: [s1] => 
  msg: |-
    "s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
    "s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"    

将内容复制到文件中:

    - copy:
        dest: /tmp/show01.txt
        content: |-
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true
      delegate_to: localhost

结果是

shell> cat /tmp/show01.txt 
"s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"

追加内容到文件中:

    - lineinfile:
        dest: /tmp/show01.txt
        regexp: '^$'
        line: |-
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true
      delegate_to: localhost

结果是

shell> cat /tmp/show01.txt 
"s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s1" "Sun Jun 25 12:52:03 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:52:03 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
英文:

Write the content in single task

Write all records into the file in a single task. It's more efficient and you'll avoid the potential race conditions by parallel writing to the same file. For example, in the play below, register the output of the commands in the variable out and display the records in the single debug

shell> cat pb.yml
- hosts: all

  tasks:

    - shell: "date; uname -smr"
      register: out

    - debug:
        msg: |
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true

gives

shell> ansible-playbook pb.yml

PLAY [all] ************************************************************************************

TASK [shell] **********************************************************************************
changed: [s1]
changed: [s2]

TASK [debug] **********************************************************************************
ok: [s1] => 
  msg: |-
    "s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
    "s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"    

Copy the content to a file

You can copy the content to a file. For example,

    - copy:
        dest: /tmp/show01.txt
        content: |-
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true
      delegate_to: localhost

gives

shell> cat /tmp/show01.txt 
"s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"

Append the content to a file

If you repeat it, the above copy task will overwrite the content of the file. If you want to append the content, use lineinfile. For example,

    - lineinfile:
        dest: /tmp/show01.txt
        regexp: '^$'
        line: |-
          {% for h in ansible_play_hosts %}
          "{{ h }}" "{{ hostvars[h].out.stdout_lines|join('" "') }}"
          {% endfor %}          
      run_once: true
      delegate_to: localhost

gives

shell> cat /tmp/show01.txt 
"s1" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:46:55 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s1" "Sun Jun 25 12:52:03 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"
"s2" "Sun Jun 25 12:52:03 UTC 2023" "FreeBSD 13.0-RELEASE-p13 amd64"

<hr>

<sup>

Example of a complete playbook for testing

- hosts: all

  vars:

    content: |-
      {% for h in ansible_play_hosts %}
      &quot;{{ h }}&quot; &quot;{{ hostvars[h].out.stdout_lines|join(&#39;&quot; &quot;&#39;) }}&quot;
      {% endfor %}      

  tasks:

    - shell: &quot;date; uname -smr&quot;
      register: out

    - block:

        - debug:
            msg: &quot;{{ content }}&quot;

        - copy:
            dest: /tmp/show01.txt
            content: &quot;{{ content }}&quot;
          when: not append|d(false)|bool

        - lineinfile:
            dest: /tmp/show01.txt
            regexp: &#39;^$&#39;
            line: &quot;{{ content }}&quot;
          when: append|d(false)|bool

      run_once: true
      delegate_to: localhost

</sup>

<hr>

Q: What &quot;|-&quot; does in &quot;content: |-&quot; ?

A: The dash - after the literal block | asks to strip the final line break. See Block Chomping Indicator. The module copy doesn't care and always strips the final break if present, but the lineinfile module obeys the format of line. When you remove the dash -

    content: |
      {% for h in ansible_play_hosts %}
      &quot;{{ h }}&quot; &quot;{{ hostvars[h].out.stdout_lines|join(&#39;&quot; &quot;&#39;) }}&quot;
      {% endfor %}      

You will get by lineinfile (note the last empty line)

shell&gt; cat /tmp/show01.txt
&quot;s1&quot; &quot;Wed Jun 28 02:06:32 UTC 2023&quot; &quot;FreeBSD 13.0-RELEASE-p13 amd64&quot;
&quot;s2&quot; &quot;Wed Jun 28 02:06:32 UTC 2023&quot; &quot;FreeBSD 13.0-RELEASE-p13 amd64&quot;

However, the code is robust enough to deal with it. The parameter regexp: &#39;^$&#39; looks for an empty line to be replaced (always the last line if present). If the regular expression is not matched (you strip the final beak), the line will be added to the file in keeping with insertbefore or insertafter settings. The default is insertafter EOF.

huangapple
  • 本文由 发表于 2023年6月25日 17:53:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76549808.html
匿名

发表评论

匿名网友

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

确定