如何将服务列表的日期转换为纪元?

问题描述 投票:0回答:1

以下是用于选择已运行超过一定时间的服务的 Ansible 代码:

---
- name: Find running services
  hosts: remote_host
  gather_facts: no

  vars:
    hours_threshold: 15  

  tasks:
    - name: Get list of running services
      command: systemctl list-units --type=service --state=running 
      register: running_services

    - name: Filter services
      set_fact:
        s_services: >-
          {{
            running_services.stdout_lines
            | select('search', 'nginx’)
            | list
          }}

    - name: result
      debug:
        msg: "{{ s_services }}"

    - name: Get details of services
      command: systemctl show {{ item }} --property=ActiveEnterTimestamp
      register: s_service_details
      loop: "{{ s_services }}"
      when: s_services | length > 0

    - name: Debug output of Redis services with start time
      debug:
        msg: "s service: {{ item.item }} started at {{ item.stdout }}"
      loop: "{{ s_service_details.results }}"
      when: s_service_details.results | length > 0

    - name: s_service_details.results
      debug:
        msg: "{{ s_service_details.results }}"

    - name: Set the threshold time for filtering
      command: date -d "{{ hours_threshold }} hours ago" +%s
      register: threshold_time

    - name: threshold_time
      debug:
        msg: "{{ threshold_time }}"

    - name: Extract and convert ActiveEnterTimestamp to epoch
      set_fact:
        redis_service_details_epoch: >-
          {{
            redis_service_details.results
            | map(attribute='stdout')
            | map('regex_findall', 'ActiveEnterTimestamp=(.*)')
            | map('first')
            | select('match', '.+') 
            | map('trim')
            | zip(redis_services | map('regex_replace', '.[^.]*$', ''))  
            | map('join', ' : ')
            | map('first')
            | map('to_datetime', '%a %Y-%m-%d %H:%M:%S %Z')
            | map('timestamp')
            | list
          }}

    - name: s_service_details_epoch
      debug:
        msg: "{{ redis_service_details_epoch }}"


任务“设置过滤的阈值时间”从设置的值中获取纪元格式的时间戳。使用此标签,您需要比较每个服务的启动时间以及工作时间超过设定值的服务,将它们输出到最终列表,以便循环运行列表数据并调用所需的playbook。将找到的每个服务的名称依次作为变量“service_name”传递。

但是,在循环中,不可能执行这样的转换。我遇到错误。

在该代码块的输出处


 | map(attribute='stdout')
            | map('regex_findall', 'ActiveEnterTimestamp=(.*)')
            | map('first')
            | select('match', '.+') 
            | map('trim')
            | zip(redis_services | map('regex_replace', '.[^.]*$', ''))  
            | map('join', ' : ')

我得到一个像这样的值:

 "Fri 2024-10-18 22:26:53 CEST : nginx-reactive"


然后需要转换为格式:

 "1729181112 : nginx-reactive"


然后您需要将每个找到的服务的所有纪元值与变量中的值进行比较:threshold_time

然后,您需要将结果列表保存到一个单独的变量中,以便您进一步使用。

这是执行单个服务转换的方法:


---
- name: Find running Redis services
  hosts: localhost
  gather_facts: no

  vars:
    expire_date: Thu 2024-09-17 11:05:12 CEST    

  tasks:
    - name: Convert expire_date to epoch
      set_fact:
        expire_date_epoch: "{{ (expire_date | to_datetime('%a %Y-%m-%d %H:%M:%S %Z')).timestamp() | int }}"

    - name: Display epoch time
      debug:
        msg: "Epoch time: {{ expire_date_epoch }}"

,但目前我只知道这些

有人对如何执行转换有任何想法吗?

ansible
1个回答
0
投票

获得正在运行的服务后

    - command: systemctl list-units --type=service --state=running
      register: running_services

使用过滤器 community.general.jc 解析 stdout。您必须在控制器上安装 jc

  rs_list: "{{ running_services.stdout | community.general.jc('systemctl') }}"

给予

  rs_list:
    - {active: active, description: Accounts Service, load: loaded, sub: running, unit: accounts-daemon.service}
    - {active: active, description: ACPI event daemon, load: loaded, sub: running, unit: acpid.service}
   ...

在您的示例中,您正在寻找 nginx 服务。我在没有安装 nginx 的笔记本上运行这个示例。让我们测试一下 ssh

  s_services: "{{ rs_list | selectattr('unit', 'match', 'ssh') }}"

给予

  s_services:
  - active: active
    description: OpenBSD Secure Shell server
    load: loaded
    sub: running
    unit: ssh.service

然后迭代此列表并获取属性 ActiveEnterTimestamp

    - command: systemctl show {{ item.unit }} --property=ActiveEnterTimestamp
      loop: "{{ s_services }}"
      register: s_service_details

当你迭代结果时

    - debug:
        msg: "{{ item.item.unit }} started at {{ item.stdout }}"
      loop: "{{ s_service_details.results }}"

给出(删节)

  msg: ssh.service started at ActiveEnterTimestamp=Mon 2024-10-14 17:06:28 CEST

声明单位列表、stdout,并创建字典 s_dict

    s_stdt: "{{ s_service_details.results | map(attribute='stdout') |
                                            map('split', '=') |
                                            map('last') }}"
    s_unit: "{{ s_service_details.results | map(attribute='item.unit') |
                                            map('split', '.') |
                                            map('first') }}"
    s_dict: "{{ dict(s_unit | zip(s_stdt)) }}"

给予

  ['Mon 2024-10-14 17:06:28 CEST']
  ['ssh']
  {'ssh': 'Mon 2024-10-14 17:06:28 CEST'}

迭代字典并将日期转换为纪元

    - debug:
        msg: "{{ item.key }} {{ (item.value | to_datetime('%a %Y-%m-%d %H:%M:%S %Z')).strftime('%s') }}"
      loop: "{{ s_dict | dict2items }}"

给予

  msg: ssh 1728918388

进一步处理应该是微不足道的。


用于测试的完整剧本示例

- hosts: localhost

  vars:

    rs_list: "{{ running_services.stdout | community.general.jc('systemctl') }}"
    s_services: "{{ rs_list | selectattr('unit', 'match', 'ssh') }}"
    s_stdt: "{{ s_service_details.results | map(attribute='stdout') |
                                            map('split', '=') |
                                            map('last') }}"
    s_unit: "{{ s_service_details.results | map(attribute='item.unit') |
                                            map('split', '.') |
                                            map('first') }}"
    s_dict: "{{ dict(s_unit | zip(s_stdt)) }}"

  tasks:

    - command: systemctl list-units --type=service --state=running
      register: running_services

    - debug:
        var: rs_list | to_yaml

    - debug:
        var: s_services

    - command: systemctl show {{ item.unit }} --property=ActiveEnterTimestamp
      loop: "{{ s_services }}"
      register: s_service_details

    - debug:
        msg: "{{ item.item.unit }} started at {{ item.stdout }}"
      loop: "{{ s_service_details.results }}"

    - debug:
        msg: |
          {{ s_stdt }}
          {{ s_unit }}
          {{ s_dict }}

    - debug:
        msg: "{{ item.key }} {{ (item.value | to_datetime('%a %Y-%m-%d %H:%M:%S %Z')).strftime('%s') }}"
      loop: "{{ s_dict | dict2items }}"
© www.soinside.com 2019 - 2024. All rights reserved.