Ansible:在文件中的现有行上插入一个单词
Ansible: insert a single word on an existing line in a file
我必须使用 Ansible 模块来编辑 /etc/ssh/sshd_config 文件——每次我创建一个新用户时,我都想将其附加到这两行:
AllowUsers root osadmin <new_user>
AllowGroups root staff <new_group>
目前我正在使用 shell 模块执行 sed 命令,但如果可能的话我想使用 lineinfile
- shell: "sed -i '/^Allow/ s/$/ {{ user_name }}/' /etc/ssh/sshd_config"
如有任何建议,我们将不胜感激。
您可以使用换行符在一次播放中完成,但我认为为此使用两次 lineinfile
播放更干净。
- hosts: '127.0.0.1'
vars:
usernames:
- larry
- curly
- moe
usergroups:
- stooges
- admins
tasks:
- lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: "AllowUsers {{usernames | join(' ')}}"
- lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowGroups'
line: "AllowGroups {{usergroups | join(' ')}}"
请注意 groups
是保留字,因此不要将其用作变量名。
replace module 将替换文件中正则表达式模式的所有实例。编写一个任务来匹配 AllowUsers
行并将其替换为附加用户名的原始行。为确保任务是幂等的,正则表达式中的否定先行断言会检查用户名是否已出现在该行中。例如:
- name: Add user to AllowUsers
replace:
backup: yes
dest: /etc/ssh/sshd_config
regexp: '^(AllowUsers(?!.*\b{{ user_name }}\b).*)$'
replace: ' {{ user_name }}'
这对我有用
- name: Add Group to AllowGroups
lineinfile:
dest=/etc/ssh/sshd_config
backup=True
backrefs=True
state=present
regexp='^(AllowGroups(?!.*\b{{ groupname }}\b).*)$'
line=' {{ groupname }}'
我遇到了同样的问题。我需要将用户添加到 sudoers 组,假设 'testuser' 到行:
User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3
这对我来说效果很好:
- name: add testuser to end of line
lineinfile:
dest: /etc/sudoers.d/somegroup
state: present
regexp: '^(User_Alias(.*)$)'
backrefs: yes
line: ', testuser'
关键是如果我在正则表达式中有 '^User_Alias(..)$'* 而不是 '^(User_Alias(..)$)'* 它不起作用,整行都被替换了。使用 () arround searched text 结果是好的:
User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3, testuser
那么任何东西都可以在 line: 中工作,包括像 "{{ usernames | join(', ') }}"
这样的 ansible 变量
所选答案假定完整的用户列表在运行时可用,而当用户名中有破折号时,最受欢迎的答案可能会失败,因为 \b
将其解释为单词边界。以下解决方案假设剧本无法从头开始重新生成完整的用户名列表,并尝试处理破折号的极端情况:
name: add a user to the list of AllowUsers if not present
lineinfile:
path: /etc/ssh/sshd_config
backrefs: yes
backup: yes
regexp: "^AllowUsers((?:(?:\s+\S+(?!\S))(?<!\s{{ username }}))+\s*?)(\n?)$"
line: "AllowUsers {{ username }}"
validate: /usr/sbin/sshd -t -f %s
作为奖励,我加入了 sshd_config 备份和验证。
正则表达式(有趣的部分)的工作原理:
--------------------------+----------------------------------------------------
( |
--------------------------+----------------------------------------------------
(?: | This group is not captured
--------------------------+----------------------------------------------------
(?:\s+\S+(?!\S)) | Matches any sequence of whitespace characters fol-
| lowed by any sequence of non-whitespace characters,
| that is to say a leading space and a username. The
| negative look-ahead at the end prevents a "catast-
| rophic backtracking". Also, this group is not cap-
| tured.
--------------------------+----------------------------------------------------
(?<!\s{{ username }}) | Applies a negative look-behind on the username, so
| that if the username found by the previous expres-
| sion matches, the regular expression fails. The
| match on a leading whitespace character ensures
| that the comparison is made on the complete string.
--------------------------+----------------------------------------------------
)+ | Groups the detection of a username and its negative
| look-behind together. The "+" quantifier is used
| here on the assumption that the file already cont-
| ains at least one username, but "*" could be used
| for a more relaxed matching.
--------------------------+----------------------------------------------------
\s*? | Matches any trailing whitespace. The match is lazy
| in order to detect the newline character later on.
--------------------------+----------------------------------------------------
) | Captures the whole text after "AllowUsers" (this
| will be ).
--------------------------+----------------------------------------------------
(\n?) | Captures either a newline character or an empty
| string (this will be ).
--------------------------+----------------------------------------------------
如果正则表达式匹配,说明该行存在,不包含{{ username }}
,所以追加
如果正则表达式不匹配,则表示该行不存在或包含{{ username }}
,我们什么也不做。
我必须使用 Ansible 模块来编辑 /etc/ssh/sshd_config 文件——每次我创建一个新用户时,我都想将其附加到这两行:
AllowUsers root osadmin <new_user>
AllowGroups root staff <new_group>
目前我正在使用 shell 模块执行 sed 命令,但如果可能的话我想使用 lineinfile
- shell: "sed -i '/^Allow/ s/$/ {{ user_name }}/' /etc/ssh/sshd_config"
如有任何建议,我们将不胜感激。
您可以使用换行符在一次播放中完成,但我认为为此使用两次 lineinfile
播放更干净。
- hosts: '127.0.0.1'
vars:
usernames:
- larry
- curly
- moe
usergroups:
- stooges
- admins
tasks:
- lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: "AllowUsers {{usernames | join(' ')}}"
- lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowGroups'
line: "AllowGroups {{usergroups | join(' ')}}"
请注意 groups
是保留字,因此不要将其用作变量名。
replace module 将替换文件中正则表达式模式的所有实例。编写一个任务来匹配 AllowUsers
行并将其替换为附加用户名的原始行。为确保任务是幂等的,正则表达式中的否定先行断言会检查用户名是否已出现在该行中。例如:
- name: Add user to AllowUsers
replace:
backup: yes
dest: /etc/ssh/sshd_config
regexp: '^(AllowUsers(?!.*\b{{ user_name }}\b).*)$'
replace: ' {{ user_name }}'
这对我有用
- name: Add Group to AllowGroups
lineinfile:
dest=/etc/ssh/sshd_config
backup=True
backrefs=True
state=present
regexp='^(AllowGroups(?!.*\b{{ groupname }}\b).*)$'
line=' {{ groupname }}'
我遇到了同样的问题。我需要将用户添加到 sudoers 组,假设 'testuser' 到行:
User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3
这对我来说效果很好:
- name: add testuser to end of line
lineinfile:
dest: /etc/sudoers.d/somegroup
state: present
regexp: '^(User_Alias(.*)$)'
backrefs: yes
line: ', testuser'
关键是如果我在正则表达式中有 '^User_Alias(..)$'* 而不是 '^(User_Alias(..)$)'* 它不起作用,整行都被替换了。使用 () arround searched text 结果是好的:
User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3, testuser
那么任何东西都可以在 line: 中工作,包括像 "{{ usernames | join(', ') }}"
所选答案假定完整的用户列表在运行时可用,而当用户名中有破折号时,最受欢迎的答案可能会失败,因为 \b
将其解释为单词边界。以下解决方案假设剧本无法从头开始重新生成完整的用户名列表,并尝试处理破折号的极端情况:
name: add a user to the list of AllowUsers if not present
lineinfile:
path: /etc/ssh/sshd_config
backrefs: yes
backup: yes
regexp: "^AllowUsers((?:(?:\s+\S+(?!\S))(?<!\s{{ username }}))+\s*?)(\n?)$"
line: "AllowUsers {{ username }}"
validate: /usr/sbin/sshd -t -f %s
作为奖励,我加入了 sshd_config 备份和验证。
正则表达式(有趣的部分)的工作原理:
--------------------------+----------------------------------------------------
( |
--------------------------+----------------------------------------------------
(?: | This group is not captured
--------------------------+----------------------------------------------------
(?:\s+\S+(?!\S)) | Matches any sequence of whitespace characters fol-
| lowed by any sequence of non-whitespace characters,
| that is to say a leading space and a username. The
| negative look-ahead at the end prevents a "catast-
| rophic backtracking". Also, this group is not cap-
| tured.
--------------------------+----------------------------------------------------
(?<!\s{{ username }}) | Applies a negative look-behind on the username, so
| that if the username found by the previous expres-
| sion matches, the regular expression fails. The
| match on a leading whitespace character ensures
| that the comparison is made on the complete string.
--------------------------+----------------------------------------------------
)+ | Groups the detection of a username and its negative
| look-behind together. The "+" quantifier is used
| here on the assumption that the file already cont-
| ains at least one username, but "*" could be used
| for a more relaxed matching.
--------------------------+----------------------------------------------------
\s*? | Matches any trailing whitespace. The match is lazy
| in order to detect the newline character later on.
--------------------------+----------------------------------------------------
) | Captures the whole text after "AllowUsers" (this
| will be ).
--------------------------+----------------------------------------------------
(\n?) | Captures either a newline character or an empty
| string (this will be ).
--------------------------+----------------------------------------------------
如果正则表达式匹配,说明该行存在,不包含{{ username }}
,所以追加
如果正则表达式不匹配,则表示该行不存在或包含{{ username }}
,我们什么也不做。