Ansible从列表生成字典时遇条目被覆盖问题求助
我的Ansible密码生成问题:循环添加条目总是覆盖旧内容
最近在折腾Ansible给一批用户批量生成随机密码,结果卡壳了——每次循环新增密码条目,都会把之前的内容给覆盖掉,完全达不到我要的字典键值对效果!
具体情况:
- 我的输入是存在
accounts_list变量里的用户列表,格式如下:
account: - PR_user1 - PR_user2
- 需求很简单:给每个用户生成随机密码,后续用来配置服务,最后导出到文本文件。现在卡在第一步:遍历这个列表生成密码,并存成
{用户名: 密码}的字典格式。 - 我参照了相关思路,尝试了两种向变量添加条目的方法(
combine和列表拼接+),写的Playbook代码是这样的:
- set_fact: # 第一种尝试:用combine合并字典 # domain_accounts: "{{ domain_accounts|default({}) | combine({item|trim: lookup('password', '/dev/null length=8 chars=ascii_letters,digits,punctuation')}) }}" # 第二种尝试:用+拼接列表 domain_accounts: "{{ domain_accounts|default([]) + [{item|trim: lookup('password', '/dev/null length=8 chars=ascii_letters,digits,punctuation')}] }}" with_items: "{{account_list.accounts}}"
- 但执行后每次循环都把之前的结果覆盖了,输出日志是这样的:
TASK [set account passwords] ****************************************************************** ok: [localhost] => (item=PR_user1) => {"ansible_facts": {"domain_accounts": [{"PR_user1": "u]oT,cU{"}]}, "changed": false, "item": "PR_user1"} ok: [localhost] => (item=PR_user2) => {"ansible_facts": {"domain_accounts": [{"PR_user2": "b>npKZdi"}]}, "changed": false, "item": "PR_user2"}
解决办法
问题根源其实很明确:Ansible循环中每次执行set_fact时,domain_accounts的default值会被重新触发,相当于每次都从零开始创建变量,而不是基于上一次循环的结果累加。
给你两种靠谱的解决方式:
方法1:用combine生成完整字典(推荐)
如果你的目标是生成标准的键值对字典,直接修改set_fact,确保每次循环都把新的键值对合并到已存在的字典里:
- set_fact: domain_accounts: "{{ domain_accounts | default({}) | combine({ item|trim: lookup('password', '/dev/null length=8 chars=ascii_letters,digits,punctuation') }, recursive=True) }}" with_items: "{{ account_list.accounts }}"
执行后就能得到一个包含所有用户和对应密码的字典,不会再出现覆盖问题。
方法2:用列表拼接时合并循环结果
如果坚持要列表套字典的格式,可以先把每次循环的结果存起来,再统一合并:
- set_fact: domain_accounts: "{{ domain_accounts | default([]) + [{ item|trim: lookup('password', '/dev/null length=8 chars=ascii_letters,digits,punctuation') }] }}" with_items: "{{ account_list.accounts }}" register: password_results - set_fact: domain_accounts: "{{ password_results.results | map(attribute='ansible_facts.domain_accounts') | flatten }}"
第一步把每次循环的结果注册到password_results里,第二步用map和flatten把所有零散的列表合并成一个完整的列表。
验证效果
不管用哪种方法,最终你都能得到包含所有用户密码的集合,比如字典形式的结果会是:
"domain_accounts": { "PR_user1": "u]oT,cU{", "PR_user2": "b>npKZdi" }
内容的提问来源于stack exchange,提问作者Ali Khawaja
相关产品推荐
相关产品推荐

