未指定主机运行Ansible Playbook报错,求解决方案
问题原因
Ansible在启动执行Playbook时会提前加载整个inventory文件,第一个play修改inventory文件后,第二个play并不会自动重新加载更新后的inventory,所以第一次运行时all组没有主机,触发警告;第二次运行时,Ansible才会读取修改后的inventory文件,任务正常执行。
解决方法
方法一:用add_host动态添加主机(推荐)
放弃修改本地inventory文件,直接在Playbook中读取用户提供的主机列表,动态添加到临时inventory中,第二个play直接使用这个临时组。
修改后的Playbook示例:
--- - hosts: localhost gather_facts: no tasks: - name: 读取用户提供的主机列表文件 command: cat 你的主机文本文件名.txt register: host_list_output - name: 动态添加主机到临时分组 add_host: name: "{{ item }}" groups: target_hosts loop: "{{ host_list_output.stdout_lines }}" # 跳过空行 when: item | trim != "" --- - hosts: target_hosts remote_user: root gather_facts: no vars: user_hash_password: "{{ user_password | password_hash('sha512') }}" tasks: - include_vars: yamlvariable.yml - name: 一次性生成所有机器的密码 set_fact: user_password: "{{ lookup('password', '/dev/null length=20') }}" run_once: true
方法二:拆分Playbook用脚本串联
如果必须修改本地inventory文件,把两个play拆成独立的Playbook,用shell脚本先执行更新inventory的任务,再执行后续任务。
- 创建
update_inventory.yml:
--- - hosts: localhost gather_facts: no tasks: - name: 运行脚本更新inventory shell: ./add_host_to_inventory.sh ignore_errors: true
- 创建
main_tasks.yml:
--- - hosts: all remote_user: root gather_facts: no vars: user_hash_password: "{{ user_password | password_hash('sha512') }}" tasks: - include_vars: yamlvariable.yml - name: 一次性生成所有机器的密码 set_fact: user_password: "{{ lookup('password', '/dev/null length=20') }}" run_once: true
- 创建执行脚本
run_playbooks.sh:
#!/bin/bash ansible-playbook update_inventory.yml ansible-playbook main_tasks.yml
给脚本加执行权限后运行:chmod +x run_playbooks.sh && ./run_playbooks.sh
方法三:用meta: refresh_inventory刷新inventory
如果你的Ansible版本≥2.7,可以在第一个play修改完inventory后,强制刷新inventory,让第二个play读取更新后的文件。
修改后的Playbook:
--- - hosts: localhost gather_facts: no tasks: - name: 运行脚本更新inventory shell: ./add_host_to_inventory.sh ignore_errors: true - name: 强制刷新inventory meta: refresh_inventory --- - hosts: all remote_user: root gather_facts: no vars: user_hash_password: "{{ user_password | password_hash('sha512') }}" tasks: - include_vars: yamlvariable.yml - name: 一次性生成所有机器的密码 set_fact: user_password: "{{ lookup('password', '/dev/null length=20') }}" run_once: true
注意:如果你的inventory不是默认路径,需要在运行Playbook时用-i参数指定路径,确保刷新的是正确的文件。
内容的提问来源于stack exchange,提问作者user20860852
相关产品推荐
相关产品推荐

