You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历Ansible清单主机名出现混乱及WordPress密码更新失败问题

问题场景

清单配置

[servers]
host1 ansible_ssh_host=xxx
host2 ansible_ssh_host=xxx

剧本内容

- name: Setup
  hosts: servers
  gather_facts: false
  remote_user: ansible
  become: true
  roles:
  - task

调试用角色任务

- name: Show all the hosts in the inventory
  ansible.builtin.debug:
    msg: "{{ item }}"
  loop: "{{ query('inventory_hostnames', 'all') }}"

调试任务执行结果

执行剧本后出现主机循环混乱,输出如下:

TASK [task : Show all the hosts in the inventory] ***************************************************************
ok: [host1] => (item=host1) => {
    "msg": "host1"
}
ok: [host2] => (item=host1) => {
    "msg": "host1"
}
ok: [host1] => (item=host2) => {
    "msg": "host2"
}
ok: [host2] => (item=host2) => {
    "msg": "host2"
}

实际任务及报错

尝试在数百台服务器上执行WordPress管理员密码更新任务:

- name: Update admin user's password
  command: wp user update admin
           --user_pass="{{ wp_admin_pwd }}"
  args:
      chdir: "/var/www/{{ item }}"
  become: yes
  become_user: www-data
  with_items: "{{ query('inventory_hostnames', 'all') }}"

执行后大量报错,示例错误信息:

failed: [host1] (item=host2) => {"ansible_loop_var": "item", "changed": false, "cmd": "", "delta": null, "end": null, "item": "host2",
"msg": "Unable to change directory before execution: [Errno 2] No such file or directory: b'/var/www/host2'"

问题核心:wp-cli必须在站点根目录执行,但当前循环方式错误,导致在host1上尝试访问host2的目录,引发不存在的路径错误。


解决方案

错误原因

使用query('inventory_hostnames', 'all')作为循环源,会让每一台目标主机都遍历整个清单的所有主机。也就是说,host1会循环处理host1和host2,host2也会循环处理host1和host2,最终导致在host1上尝试进入仅存在于host2的目录,触发报错。

修正方法

方法1:针对当前主机直接操作

不需要循环清单主机,直接使用Ansible内置变量inventory_hostname(代表当前执行任务的主机名):

- name: Update admin user's password
  command: wp user update admin --user_pass="{{ wp_admin_pwd }}"
  args:
      chdir: "/var/www/{{ inventory_hostname }}"
  become: yes
  become_user: www-data

这样每台主机只会处理自己对应的站点目录,避免跨主机路径错误。

方法2:单主机多站点场景适配

如果单台主机上部署了多个WordPress站点,可在主机变量中定义站点列表,循环站点而非主机:

  1. 修改清单,给主机添加站点变量:
[servers]
host1 ansible_ssh_host=xxx wp_sites=["site1", "site2"]
host2 ansible_ssh_host=xxx wp_sites=["site3"]
  1. 更新任务,循环站点列表:
- name: Update admin user's password for all sites
  command: wp user update admin --user_pass="{{ wp_admin_pwd }}"
  args:
      chdir: "/var/www/{{ item }}"
  become: yes
  become_user: www-data
  loop: "{{ wp_sites }}"

补充说明

  • 若站点目录命名规则与主机名不一致,可在清单中给每个主机单独定义wp_site_dir变量,任务中直接引用{{ wp_site_dir }}即可。
  • 仅当需要在每台主机上遍历所有其他主机时,才使用query('inventory_hostnames')做任务循环,日常单主机任务无需此操作。

内容的提问来源于stack exchange,提问作者Roberto Jobet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:10:42