来自输出的Ansible变量

时间:2018-03-30 12:38:21

标签: ansible jinja2 ansible-template

我想从Ansible输出中提取一些单词。例如,我想从sudo monit status命令中提取粗体字(** **)并将它们存储在2个变量中(假设变量'A'代表OK,变量'B'代表正常运行时间段)稍后将用于Jinja2模板:

[ansible@server ~]$ sudo monit status
Monit 5.25.1 uptime: 3m

System 'server'
  status                       **OK**
  monitoring status            Monitored
  monitoring mode              active
  on reboot                    start
  load average                 [0.03] [0.07] [0.11]
  cpu                          0.1%us 0.2%sy 0.0%wa
  memory usage                 338.1 MB [18.4%]
  swap usage                   0 B [0.0%]
  uptime                       **29m**
  boot time                    Fri, 30 Mar 2018 11:56:12
  data collected               Fri, 30 Mar 2018 12:25:24

为了实现这一点,我已经开始使用Ansible剧本,但是通过这种方式,我将从输出中获取所有信息:

--- #Health check
- hosts: appserver
  connection: ssh 
  sudo: yes 
  user: ansible
  tasks:
  - name: Monitor the status
    shell: "{{item}}"
    with_items:
      - monit status 
    register: monitinfo
    tags: basic_monitoring
  - debug: var=monitinfo

知道如何实现这一目标吗?

谢谢,

罗曼

1 个答案:

答案 0 :(得分:1)

我看到两种解决问题的方法:

方法1:将shell输出转换为YAML或JSON并使用from_yaml或from_json

解析它

在您的特定情况下,由于输出已经以键值方式预先格式化,因此将其转换为Ansible理解的格式(例如YAML / JSON)将是最方便的。例如,您可以通过删除tail不相关的行来将输出转换为YAML,然后使用regex_replace filter。然后,使用from_yaml filter将所有内容解析为Ansible变量。例如:

- name: Fetch the monit status
  shell: "monit status | tail -n +3"
  register: monit_status_raw
- name: Extract monit variables
  set_fact:
     monit_status: "{{ monit_status_raw.stdout | regex_replace('\s\s([a-z]+\s[a-z]*)\s+', '\\1: ') | regex_replace('\s:', ':') | regex_replace('([a-z])\s([a-z])', '\\1_\\2')  | from_yaml }}"
- name: Show server status 
  debug: var=monit_status['status']
- name: Show server uptime
  debug: var=monit_status['uptime']

如果一切正常,monit_status变量应该包含monit status命令提供的所有变量的字典。您可以访问所需的变量,如上例中的debug命令所示。如果代码不起作用,您可以使用

调试regex_replace过滤器
- debug: msg="{{ monit_status_raw.stdout | regex_replace('\s\s([a-z]+\s[a-z]*)\s+', '\\1: ') | regex_replace('\s:', ':') | regex_replace('([a-z])\s([a-z])', '\\1_\\2')  | from_yaml }}"

并检查输出是否已经是YAML。如果没有,则必须调整正则表达式,以便最终输出符合YAML。

方法2:使用regex_search过滤器

搜索所需的值

在类似的情况下,只需要提取单个变量,或者输出无法使用regex_replace轻松转换为JSON或YAML,regex_search过滤器将是正确的选择。在您的情况下,regex_search解决方案看起来与此类似:

- name: Fetch the monit status
  shell: "monit status | tail -n +3"
  register: monit_status_raw
- name: Extract monit variables
  set_fact:
     monit_status: "{{ monit_status_raw.stdout | regex_search('\s\sstatus\s+(.*)') }}"
     monit_uptime: "{{ monit_status_raw.stdout | regex_search('\s\suptime\s+(.*)') }}"
- name: Show server status 
  debug: var=monit_status
- name: Show server uptime
  debug: var=monit_uptime

提示:像regex101.com这样的在线正则表达式测试人员可以帮助您找到正确的表达方式。