Ansible:如何从文件的内容中提取特定的字符串?



我试图让Ansible读取文件并选择我的搜索参数的第一个匹配,以及删除不需要的文本。

例如,我有

下面的文件
<Proxy balancer://${balancerNameEAPI}>
#  BalancerMember https://server1.domain.com:port hctemplate=tcp
BalancerMember https://server2.domain.com:port hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>
<Proxy balancer://${balancerNamePAPI}>
#  BalancerMember https://server1.domain.com:port hctemplate=tcp
BalancerMember https://server2.domain.com:port hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>
<Proxy balancer://${balancerNameSAPI}>
#  BalancerMember https://server1.domain.com:port hctemplate=tcp
BalancerMember https://server2.domain.com:port hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>

我需要对注释掉的备用主机采取行动,在这种情况下是server1

我使用下面的脚本读取这个配置文件,并取出包含正确主机的行。

---
- name: test read file
hosts: localhost
gather_facts: false
vars:
source_file: /files/test/test.cfg
host_to_patch: []
tasks:
- set_fact:
host_to_patch: "{{ host_to_patch + [ item ] }}"
with_lines: "cat {{ source_file }}"
when: item is search('^#  BalancerMember https://server')
- debug:
var: host_to_patch

这当然给了我整行三次的输出,我只对该行的server1.domain.com部分感兴趣,此时我只需要第一个匹配。我想告诉Ansible这是剧本中另一个游戏的目标主机名。这样做的原因是,文件中的服务器是一对活动的备用服务器,我需要从备用主机开始,每次执行一个,每个月可能不同。

下面是当前的输出

ok: [localhost] => {
"host_to_patch": [
"#  BalancerMember https://server1.domain.com:port hctemplate=tcp",
"#  BalancerMember https://server1.domain.com:port hctemplate=tcp",
"#  BalancerMember https://server1.domain.com:port hctemplate=tcp"
]
}

如果有任何进一步的信息会有帮助,请让我知道,并提前感谢!

用例

我正试图让Ansible读取文件并选择我的搜索参数的第一个匹配,以及删除不需要的文本。

假设您的配置示例文件中的结构保持原样,并且您正在寻找一个完整的Ansible等效于我如何在匹配后grep一个单词?

- name: Gather standby hostname
shell:
cmd: grep -Po 'https://K.*' test.cfg | head -1 | cut -d ':' -f 1
register: standby_hostname
解决方案

您可以查看slurp模块-从远程节点和最小示例playbook中Slurps文件

---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Read config file
slurp:
src: test.cfg
register: config
- name: Show config file
debug:
msg: "{{ config['content'] | b64decode }}"
- name: Show first result
debug:
msg: "{{ config['content'] | b64decode | regex_findall('https://(.+)') | first | split(':') | first }}"

,结果是输出

TASK [Show first result] ******
ok: [localhost] =>
msg: server1.domain.com

使用slurp模块

…用于获取包含远程文件中数据的base64编码blob。

因此b64decode过滤器-解码base64字符串是进一步处理所必需的。

regex_findall过滤器-从字符串中提取https://(.+)匹配后的所有regex匹配。

因为它将提供一个列表,Jinja2 Filterfirst将只给出第一个结果。

split过滤器-将字符串与first过滤器一起拆分为列表,然后用于获得:分隔结果集的左侧。

类似Q&

  • 如何从文件中读取一行到Ansible变量?
  • slurp可以直接替代lookup吗?

进一步文档

  • 使用过滤器操作数据
  • Jinja2模板设计器文档-过滤器和内置过滤器列表

给定文件

shell> cat /tmp/config.xml 
<Proxy balancer://${balancerNameEAPI}>
#  BalancerMember https://server1.domain.com:65535 hctemplate=tcp
BalancerMember https://server2.domain.com:65535 hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>
<Proxy balancer://${balancerNamePAPI}>
#  BalancerMember https://server1.domain.com:65535 hctemplate=tcp
BalancerMember https://server2.domain.com:65535 hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>
<Proxy balancer://${balancerNameSAPI}>
#  BalancerMember https://server1.domain.com:65535 hctemplate=tcp
BalancerMember https://server2.domain.com:65535 hctemplate=tcp
ProxySet lbmethod=bybusyness
</Proxy>

读取文件

- name: Read config file
slurp:
src: /tmp/config.xml
register: config

和声明变量

_regex1: '^s*#s*BalancerMember https://server.*$'
_regex2: 'bhttpsS*'
hosts_to_patch: "{{ (config.content|b64decode).splitlines()|
select('regex', _regex1)|
map('regex_search', _regex2)|
map('urlsplit', 'hostname')|
unique }}"

hosts_to_patch:
- server1.domain.com

用于测试的完整剧本示例

- hosts: localhost
vars:
_regex1: '^s*#s*BalancerMember https://server.*$'
_regex2: 'bhttpsS*'
hosts_to_patch: "{{ (config.content|b64decode).splitlines()|
select('regex', _regex1)|
map('regex_search', _regex2)|
map('urlsplit', 'hostname')|
unique }}"

tasks:
- name: Read config file
slurp:
src: /tmp/config.xml
register: config
- debug:
var: hosts_to_patch

最新更新