Ansible Playbook:如何将无法访问的清单主机名写入文件

Asw*_*rge 2 ansible

我正在为清单主机列表编写剧本:-

如果主机可达,则写入“connection=1”并写入文件。如果主机不可访问,写入同一个文件“connection=0”

根据我的理解,Ansible 不会以可访问的方式存储无法访问的热点信息(当 ssh 失败时)。

你能帮我吗?我的剧本贴在下面。由于主机无法访问,因此根本不执行 shell 任务

下面是我的剧本

- hosts: '{{ host }}'
  gather_facts: False
  vars:
    dest: /tmp/trace
  tasks:
    - copy:
        content: ''
        dest: "{{ dest }}"
      run_once: yes
      delegate_to: 127.0.0.1
    - shell: ping {{ inventory_hostname }}  -c 1
      register: ping_status
      ignore_errors:  yes
    - setup:
       filter: ansible_*
    - lineinfile:
        dest: "{{ dest }}"
        line: 'Host:{{ inventory_hostname }},OS:{{ ansible_distribution }},Kernel:{{ansible_kernel}},OSVersion:{{ansible_distribution_version}},FreeMemory:{{ansible_memfree_mb}},connection:{{ping_status.rc}}'
      ignore_errors: true
      delegate_to: 127.0.0.1
Run Code Online (Sandbox Code Playgroud)

lar*_*sks 5

您的剧本存在一些问题。第一个是您试图在远程主机上同时执行 ashell和setup任务,如果该主机不可用,这当然不会起作用。

ping在远程主机上运行任务甚至没有意义:您想使用委托在本地主机上运行它。我们可以做这样的事情来记录每个主机的可用性作为主机变量:

---
- hosts: all
  gather_facts: false
  tasks:
    - delegate_to: localhost
      command: ping -c1 "{{ hostvars[inventory_hostname].ansible_host|default(inventory_hostname) }}"
      register: ping
      ignore_errors: true

    - set_fact:
        available: "{{ ping.rc == 0 }}"
Run Code Online (Sandbox Code Playgroud)

您正在尝试setup针对您的远程主机运行该模块,但这仅在远程主机可用时才有意义,因此我们需要根据我们的ping任务结果进行设置:

- setup:
    filter: "ansible_*"
  when: ping.rc == 0
Run Code Online (Sandbox Code Playgroud)

有了它,我们就可以生成一个文件,其中包含有关每个主机的可用性信息。我在lineinfile这里使用是因为这就是您在示例中使用的内容,但是如果我自己写这个,我可能会使用一个template任务:

- hosts: localhost
  gather_facts: false
  tasks:
    - lineinfile:
        dest: ./available.txt
        line: "Host: {{ item }}, connection={{ hostvars[item].available }}"
        regexp: "Host: {{ item }}"
        create: true
      loop: "{{ groups.all }}"
Run Code Online (Sandbox Code Playgroud)

当然,在您的示例中,您试图包含有关主机的各种其他事实:

        line: 'Host:{{ inventory_hostname }},OS:{{ ansible_distribution }},Kernel:{{ansible_kernel}},OSVersion:{{ansible_distribution_version}},FreeMemory:{{ansible_memfree_mb}},connection:{{ping_status.rc}}'
Run Code Online (Sandbox Code Playgroud)

如果目标主机不可用,这些事实将不可用,因此您需要使用{% if <condition> %}...{% endif %}构造使所有这些条件成为条件:

line: "Host:{{ item }},connection:{{ hostvars[item].available }}{% if hostvars[item].available %},OS:{{ hostvars[item].ansible_distribution }},Kernel:{{ hostvars[item].ansible_kernel }},OSVersion:{{ hostvars[item].ansible_distribution_version }},FreeMemory:{{ hostvars[item].ansible_memfree_mb }}{% endif %}"
Run Code Online (Sandbox Code Playgroud)

这使得最终的剧本看起来像这样:

---
- hosts: all
  gather_facts: false
  tasks:
    - delegate_to: localhost
      command: ping -c1 "{{ hostvars[inventory_hostname].ansible_host|default(inventory_hostname) }}"
      register: ping
      ignore_errors: true

    - set_fact:
        available: "{{ ping.rc == 0 }}"

    - setup:
      when: ping.rc == 0

- hosts: localhost
  gather_facts: false
  tasks:
    - lineinfile:
        dest: ./available.txt
        line: "Host:{{ item }},connection:{{ hostvars[item].available }}{% if hostvars[item].available %},OS:{{ hostvars[item].ansible_distribution }},Kernel:{{ hostvars[item].ansible_kernel }},OSVersion:{{ hostvars[item].ansible_distribution_version }},FreeMemory:{{ hostvars[item].ansible_memfree_mb }}{% endif %}"
        regexp: "Host: {{ item }}"
        create: true
      loop: "{{ groups.all }}"
Run Code Online (Sandbox Code Playgroud)