以下是用于选择已运行超过一定时间的服务的 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 }}"
,但目前我只知道这些
有人对如何执行转换有任何想法吗?
获得正在运行的服务后
- 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 }}"