实时确保 ansible playbook 中的两个任务之间经过了一定的时间

Ensure a certain amount of time has elapsed between two tasks in ansible playbook, in real time

我将通知用户 15 分钟后将发生一个事件;然后我执行的任务花费的时间不定,少于 15 分钟,然后我需要等待剩下的时间,并在我通知用户后正好 15 分钟执行上述事件。

有人可以在ansible中提出这样一个实时定时器吗? pause 不起作用,因为它是静态的。此外,async 不适用于 pause 任务,因此我们无法与 poll: 0 异步启动 pause,继续执行其他任务,然后返回并确保它在我们等待的任务之前 async_status 成功。

这是我最好的尝试,但是 until 条件似乎没有根据实际当前时间进行更新,因为它永远不会终止:

- name: Ensure a certain amount of time has elapsed between two tasks
  hosts: localhost
  gather_facts: no
  vars:
    wait_time: 10
    timer_delay_interval: 1
  tasks:
    - name: Debug start time
      debug:
        var: ansible_date_time

    - name: Set current time
      set_fact:
        start_time: "{{ ansible_date_time.date }} {{ ansible_date_time.time }}"
    
    - name: Other task
      pause:
        seconds: 2

    - name: Timer
      set_fact:
        current_time: "{{ ansible_date_time.date }} {{ ansible_date_time.time }}"
      until: ((current_time | to_datetime) - (start_time | to_datetime)).total_seconds() >= wait_time
      retries: 1000000
      delay: "{{ timer_delay_interval }}"
      register: timer_task

    - name: Waited for task
      debug:
        msg: |
          The timer has completed with {{ timer_task.attempts }} attempts,
          for a total of {{ timer_task.attempts*timer_delay_interval | int }} seconds.
          The original wait time was {{ wait_time }}, which means that intervening
          tasks took {{ wait_time - timer_task.attempts*timer_delay_interval | int }} seconds.

注意:to_datetime 过滤器要求日期时间的格式类似于 %Y-%m-%d %H:%M:%S,这就是为什么我要这样设置它们的格式。

还有更多选择。

  1. 运行 个任务并发。 运行 模块 wait_for asynchronously. Then, use async_status 等待剩余的 wait_time 结束。 retries的次数是wait_timepause1秒之差delay 以确保模块将覆盖剩余时间。当然,在实践中,重试的次数会更少。请参阅下面关于 offset
  2. 的评论
- name: Ensure a certain amount of time has elapsed between two tasks
  hosts: localhost
  gather_facts: false
  vars:
    wait_time: 10
    pause: 5
    offset: 2
  tasks:
    - debug:
        msg: "start_time: {{ '%Y-%m-%d %H:%M:%S'|strftime }}"
    - wait_for:
        timeout: "{{ wait_time|int - offset|int }}"
      async: 20
      poll: 0
      register: async_result
    - pause:
        seconds: "{{ pause }}"
    - async_status:
        jid: "{{ async_result.ansible_job_id }}"
      register: job_result
      until: job_result.finished
      retries: "{{ wait_time|int - pause|int }}"
      delay: 1
    - debug:
        msg: "Something happened at {{ '%Y-%m-%d %H:%M:%S'|strftime }}"

给出(删节)

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: 'start_time: 2022-05-12 09:43:11'

TASK [wait_for] ******************************************************************************
changed: [localhost]

TASK [pause] *********************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]

TASK [async_status] **************************************************************************
FAILED - RETRYING: [localhost]: async_status (5 retries left).
FAILED - RETRYING: [localhost]: async_status (4 retries left).
ok: [localhost]

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Something happened at 2022-05-12 09:43:21

  1. 下一个选项是剩余时间的计算
- name: Ensure a certain amount of time has elapsed between two tasks
  hosts: localhost
  gather_facts: false
  vars:
    wait_time: 10
    pause: 5
    offset: 2
  tasks:
    - set_fact:
        start_time: "{{ '%Y-%m-%d %H:%M:%S'|strftime }}"
        start_time_sec: "{{ '%s'|strftime }}"
    - set_fact:
        stop_time: "{{ '%Y-%m-%d %H:%M:%S'|strftime(start_time_sec|int + wait_time|int) }}"
        stop_time_sec: "{{ start_time_sec|int + wait_time|int }}"
    - debug:
        msg: "start_time: {{ start_time }}"
    - pause:
        seconds: "{{ pause }}"
    - set_fact:
        wait_time: "{{ stop_time_sec|int - '%s'|strftime|int - offset|int }}"
    - debug:
        msg: |-
          wait_time: {{ wait_time }}
      when: debug|d(false)|bool
    - wait_for:
        timeout: "{{ wait_time|int }}"
    - debug:
        msg: "Something happened at {{ '%Y-%m-%d %H:%M:%S'|strftime }}"

给出(删节)

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: 'start_time: 2022-05-12 09:55:08'

TASK [pause] *********************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]

TASK [set_fact] ******************************************************************************
ok: [localhost]

TASK [debug] *********************************************************************************
skipping: [localhost]

TASK [wait_for] ******************************************************************************
ok: [localhost]

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Something happened at 2022-05-12 09:55:18

使 offset 适合您的系统。