Ansible wait_for模块,从文件末尾开始

时间:2016-12-18 00:11:42

标签: ansible ansible-playbook

如果我在文件

上使用wait_for,则使用Ansible中的search_regex='foo'模块

它似乎从文件的开头开始,这意味着它将匹配旧数据,因此当重新启动附加到文件而不是启动新文件的进程/应用程序(Java)时,{{1}对于旧数据,模块将退出true,但我想从文件的尾部检查。

6 个答案:

答案 0 :(得分:6)

search_regex模块的wait_for中的正则表达式默认设置为多行。

您可以注册最后一行的内容,然后搜索该行之后出现的字符串(这假设日志文件中没有重复的行,即每个行包含一个时间戳):

vars:
  log_file_to_check: <path_to_log_file>
  wanted_pattern: <pattern_to_match>

tasks:
  - name: Get the contents of the last line in {{ log_file_to_check }}
    shell: tail -n 1 {{ log_file_to_check }}
    register: tail_output

  - name: Create a variable with a meaningful name, just for clarity
    set_fact:
      last_line_of_the_log_file: "{{ tail_output.stdout }}"

  ### do some other tasks ###

  - name: Match "{{ wanted_pattern }}" appearing after "{{ last_line_of_the_log_file }}" in {{ log_file_to_check }}
    wait_for:
      path: "{{ log_file_to_check }}"
      search_regex: "{{ last_line_of_the_log_file }}\r(.*\r)*.*{{ wanted_pattern }}"

答案 1 :(得分:4)

如果日志文件中的每一行都带有时间戳,那么

techraf's answer将起作用。否则,日志文件可能有多行与最后一行相同。

更强大/持久的方法是检查日志文件当前有多少行,然后搜索在'nth'行之后发生的正则表达式/模式。


vars:
  log_file: <path_to_log_file>
  pattern_to_match: <pattern_to_match>

tasks:
  - name: "Get contents of log file: {{ log_file }}"
    command: "cat {{ log_file }}"
    changed_when: false  # Do not show that state was "changed" since we are simply reading the file!
    register: cat_output

  - name: "Create variable to store line count (for clarity)"
    set_fact:
      line_count: "{{ cat_output.stdout_lines | length }}"

##### DO SOME OTHER TASKS (LIKE DEPLOYING APP) #####

  - name: "Wait until '{{ pattern_to_match}}' is found inside log file: {{ log_file }}"
    wait_for:
      path: "{{ log_file }}"
      search_regex: "^{{ pattern_to_skip_preexisting_lines }}{{ pattern_to_match }}$"
      state: present
    vars:
      pattern_to_skip_preexisting_lines : "(.*\\n){% raw %}{{% endraw %}{{ line_count }},{% raw %}}{% endraw %}"  # i.e. if line_count=100, then this would equal "(.*\\n){100,}"

答案 2 :(得分:0)

实际上,如果您可以在Java应用程序日志文件上强制执行日志轮换,那么简单的wait_for将实现您想要的功能,因为它不会成为任何匹配的历史日志行

我正在使用这种方法滚动升级mongodb并等待&#34;等待连接&#34;在进行之前的mongod日志中。

示例任务:

tasks:
  - name: Rotate mongod logs
    shell: kill -SIGUSR1 $(pidof mongod)
    args:
      executable: /bin/bash

  - name: Wait for mongod being ready
    wait_for:
      path: /var/log/mongodb/mongod.log
      search_regex: 'waiting for connections'

答案 3 :(得分:0)

另一种方法,使用中间临时文件跟踪新记录:

- name: Create tempfile for log tailing
  tempfile:
    state: file
  register: tempfile
- name: Asynchronous tail log to temp file 
  shell: tail -n 0 -f /path/to/logfile > {{ tempfile.path }}
  async: 60
  poll: 0
- name: Wait for regex in log
  wait_for:
    path: "{{ tempfile.path }}"
    search_regex: 'some regex here'
- name: Remove tempfile
  file:
    path: "{{ tempfile.path }}"
    state: absent

答案 4 :(得分:0)

我用@Slezhuk的答案解决了我的问题。但是我发现了一个问题。剧本完成后,tail命令不会停止。它将永远运行。我不得不添加一些其他逻辑来停止该过程:

# the playbook doesn't stop the async job automatically. Need to stop it
- name: get the PID async tail
  shell: ps -ef | grep {{ tmpfile.path }} | grep tail | grep -v grep | awk '{print $2}'
  register: pid_grep
- set_fact:
    tail_pid: "{{pid_grep.stdout}}"
# the tail command shell has two processes. So need to kill both
- name: killing async tail command
  shell: ps -ef | grep " {{tail_pid}} " | grep -v grep | awk '{print $2}' | xargs kill -15
- name: Wait the tail process to be killed
  wait_for:
    path: /proc/{{tail_pid}}/status
    state: absent

答案 5 :(得分:0)

自上述以来,尝试执行类似和ansible的操作时出现在此页面上,因此这是我使用以上方法的解决方案。还将timeout linux命令与async一起使用-因此加倍。

如果应用程序轮换启动时登录会容易得多-但有些应用程序不是那样好!

按照此页面。 https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html

异步任务将一直运行,直到根据其异步值完成,失败或超时为止。

希望它对某人有帮助

- name: set some common vars
  set_fact:
    tmp_tail_log_file: /some/path/tail_file.out # I did this as I didn't want to create a temp file every time, and i put it in the same spot.
    timeout_value: 300 # async will terminate the task - but to be double sure I used timeout linux command as well.
    log_file: /var/logs/my_log_file.log
    
  - name: "Asynchronous tail log to {{ tmp_tail_log_file }}"
    shell: timeout {{ timeout_value }} tail -n 0 -f {{ log_file }} > {{ tmp_tail_log_file }}
    async: "{{ timeout_value }}"
    poll: 0

  - name: "Wait for xxxxx to finish starting"
    wait_for:
      timeout: "{{ timeout_value }}"
      path: "{{ tmp_tail_log_file }}"
      search_regex: "{{ pattern_search }}"
    vars:
      pattern_search: (.*Startup process completed.*)
    register: waitfor

  - name: "Display log file entry"
    debug:
      msg: 
        - "xxxxxx startup completed - the following line was matched in the logs"
        - "{{ waitfor['match_groups'][0] }}"