引用循环项时使用 jinja2 定界符的替代方法
Alternatives to using jinja2 delimiters when referencing loop item
此处为新手 Ansible 用户。所以我试图自动更改密码,并在播放中的循环中添加了一个条件,以便仅当用户存在于系统上时才更改密码。
我让剧本检索了所有用户的列表,然后在 运行 循环之前将其与 when
语句一起使用。
---
- hosts: localhost
become: yes
gather_facts: no
vars_files:
- /etc/ansible/userlist.yaml
tasks:
- name: definepass
ansible.builtin.shell: tail -1 passlist.yaml
register: newpassword
- name: get data
shell: "getent passwd | cut -d: -f1"
register: allusers
- name: change password
user:
name: "{{ item }}"
update_password: always
password: "{{ 'newpassword'|password_hash('sha256') }}"
loop: "{{ uservar }}"
when: '"item" in allusers'
- uservar:
- 'testuser' # real user on system
- 'testuser2' # also a real user on system
- 'fakeuser' # fake username, does not yet exist on system
- user: 'testuser'
(作为参考,当我在正常的 shell window 中执行 getent passwd | cut -d: -f1
时,我得到了我应该得到的:一长串用户名以及我想要的用户名。 )
系统似乎不理解这种情况,因为它跳过了所有用户。
TASK [definepass] *********************************************************************************************************************************************
changed: [localhost]
TASK [get data] ***********************************************************************************************************************************************
changed: [localhost]
TASK [change password] ****************************************************************************************************************************************
skipping: [localhost] => (item=testuser)
skipping: [localhost] => (item=testuser2)
skipping: [localhost] => (item=fakeuser)
PLAY RECAP ****************************************************************************************************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
(新密码本应更改为无效。)
抱歉,如果修复很简单,但我不确定如何最好地解决这个问题。
问:"条件跳过所有用户。"
A:命令的标准输出存储在已注册字典 allusers 的属性 stdout 中。在您的情况下,属性 stdout_lines 更有用。看看变量
- name: get data
shell: "getent passwd | cut -d: -f1"
register: allusers
- debug:
var: allusers
但是,在这种情况下,您应该使用 Ansible 模块 getent 而不是模块 shell。数据将自动存储在变量getent_passwd中,例如
- name: get data
getent:
database: passed
- debug:
var: getent_passwd
那么,就可以使用条件中的数据了
- debug:
msg: "{{ item }} exists on the system."
loop: "{{ uservar }}"
when: item in getent_passwd
vars:
uservar:
- 'testuser' # real user on system
- 'testuser2' # also a real user on system
- 'fakeuser' # fake username, does not yet exist on system
- admin
举个例子
skipping: [localhost] => (item=testuser)
skipping: [localhost] => (item=testuser2)
skipping: [localhost] => (item=fakeuser)
ok: [localhost] => (item=admin) =>
msg: admin exists on the system.
您可能想知道条件是如何工作的。 getent_passwd 是一个字典,测试 in 需要一个列表(Jinja 术语中的序列)。当用作列表时,字典会转换为其键的列表。
当您保留命令的注册输出时,条件的正确形式是
when: item in allusers.stdout_lines
此处为新手 Ansible 用户。所以我试图自动更改密码,并在播放中的循环中添加了一个条件,以便仅当用户存在于系统上时才更改密码。
我让剧本检索了所有用户的列表,然后在 运行 循环之前将其与 when
语句一起使用。
---
- hosts: localhost
become: yes
gather_facts: no
vars_files:
- /etc/ansible/userlist.yaml
tasks:
- name: definepass
ansible.builtin.shell: tail -1 passlist.yaml
register: newpassword
- name: get data
shell: "getent passwd | cut -d: -f1"
register: allusers
- name: change password
user:
name: "{{ item }}"
update_password: always
password: "{{ 'newpassword'|password_hash('sha256') }}"
loop: "{{ uservar }}"
when: '"item" in allusers'
- uservar:
- 'testuser' # real user on system
- 'testuser2' # also a real user on system
- 'fakeuser' # fake username, does not yet exist on system
- user: 'testuser'
(作为参考,当我在正常的 shell window 中执行 getent passwd | cut -d: -f1
时,我得到了我应该得到的:一长串用户名以及我想要的用户名。 )
系统似乎不理解这种情况,因为它跳过了所有用户。
TASK [definepass] *********************************************************************************************************************************************
changed: [localhost]
TASK [get data] ***********************************************************************************************************************************************
changed: [localhost]
TASK [change password] ****************************************************************************************************************************************
skipping: [localhost] => (item=testuser)
skipping: [localhost] => (item=testuser2)
skipping: [localhost] => (item=fakeuser)
PLAY RECAP ****************************************************************************************************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
(新密码本应更改为无效。)
抱歉,如果修复很简单,但我不确定如何最好地解决这个问题。
问:"条件跳过所有用户。"
A:命令的标准输出存储在已注册字典 allusers 的属性 stdout 中。在您的情况下,属性 stdout_lines 更有用。看看变量
- name: get data
shell: "getent passwd | cut -d: -f1"
register: allusers
- debug:
var: allusers
但是,在这种情况下,您应该使用 Ansible 模块 getent 而不是模块 shell。数据将自动存储在变量getent_passwd中,例如
- name: get data
getent:
database: passed
- debug:
var: getent_passwd
那么,就可以使用条件中的数据了
- debug:
msg: "{{ item }} exists on the system."
loop: "{{ uservar }}"
when: item in getent_passwd
vars:
uservar:
- 'testuser' # real user on system
- 'testuser2' # also a real user on system
- 'fakeuser' # fake username, does not yet exist on system
- admin
举个例子
skipping: [localhost] => (item=testuser)
skipping: [localhost] => (item=testuser2)
skipping: [localhost] => (item=fakeuser)
ok: [localhost] => (item=admin) =>
msg: admin exists on the system.
您可能想知道条件是如何工作的。 getent_passwd 是一个字典,测试 in 需要一个列表(Jinja 术语中的序列)。当用作列表时,字典会转换为其键的列表。
当您保留命令的注册输出时,条件的正确形式是
when: item in allusers.stdout_lines