仅检查文件中是否存在一行(ansible)

Ans*_*rta 47 ansible

在ansible中,我需要检查文件中是否存在特定行.基本上,我需要将以下命令转换为ansible任务.我的目标是只检查.

grep -Fxq "127.0.0.1" /tmp/my.conf
Run Code Online (Sandbox Code Playgroud)

LHS*_*now 46

一致使用check_mode,register和failed_when.如果lineinfile模块对正在检查的文件进行任何更改,则此任务将失败.Check_mode确保即使不这样也不会改变.

- name: "Ensure /tmp/my.conf contains '127.0.0.1'"
  lineinfile:
    name: /tmp/my.conf
    line: "127.0.0.1"
    state: present
  check_mode: yes
  register: conf
  failed_when: (conf is changed) or (conf is failed)
Run Code Online (Sandbox Code Playgroud)

  • 我使用这种方法,但设置`state:absent`并使用`regexp`参数而不是`line`.这给了你几乎所有使用grep的灵活性,并且注册变量中`changed'的值等于是否找到了模式. (4认同)
  • `check_mode` 的巧妙用法! (3认同)

Ant*_*des 43

- name: Check whether /tmp/my.conf contains "127.0.0.1"
  command: grep -Fxq "127.0.0.1" /tmp/my.conf
  register: checkmyconf
  check_mode: no
  ignore_errors: yes
  changed_when: no

- name: Greet the world if /tmp/my.conf contains "127.0.0.1"
  debug: msg="Hello, world!"
  when: checkmyconf.rc == 0
Run Code Online (Sandbox Code Playgroud)

更新2017-08-28:较旧的Ansible版本需要使用always_run: yes而不是check_mode: no.

  • 我承认这不是最佳解决方案,因为将它移植到 Windows 上更难。让我看看有没有别的办法……不行,我找不到其他办法。 (2认同)
  • 我认为 check_mode 在这里无效,因为它只是跳过执行检查。 (2认同)
  • 除了 `when: checkmyconf.rc == 0` 你也可以使用 `when: not checkmyconf.failed` ,它更具可读性。 (2认同)

mix*_*xja 14

使用已接受的解决方案,即使您忽略错误,如果没有匹配,您仍会在第一个任务上获得丑陋的红色错误输出:

TASK: [Check whether /tmp/my.conf contains "127.0.0.1"] ***********************
failed: [localhost] => {"changed": false, "cmd": "grep -Fxq "127.0.0.1" /tmp/my.conf", "delta": "0:00:00.018709", "end": "2015-09-27 17:46:18.252024", "rc": 1, "start": "2015-09-27 17:46:18.233315", "stdout_lines": [], "warnings": []}
...ignoring
Run Code Online (Sandbox Code Playgroud)

如果您想要更简洁的输出,可以使用awk而不是grep. awk不会在不匹配时返回错误,这意味着无论匹配或不匹配,下面的第一个检查任务都不会出错:

- name: Check whether /tmp/my.conf contains "127.0.0.1"
  command: awk /^127.0.0.1$/ /tmp/my.conf
  register: checkmyconf
  changed_when: False

- name: Greet the world if /tmp/my.conf contains "127.0.0.1"
  debug: msg="Hello, world!"
  when: checkmyconf.stdout | match("127.0.0.1")
Run Code Online (Sandbox Code Playgroud)

请注意,我的第二个任务使用匹配过滤器,因为如果找到匹配项,awk会返回匹配的字符串.

无论检查任务是否匹配,上面的替代方法都将产生以下输出:

TASK: [Check whether /tmp/my.conf contains "127.0.0.1"] ***********************
ok: [localhost]
Run Code Online (Sandbox Code Playgroud)

恕我直言这是一个更好的方法,因为你不会忽略你的第一个任务中的其他错误(例如,如果指定的文件不存在).

  • 您可以使用`failed_when:false`而不是`ignore_errors`来避免错误消息. (4认同)

Don*_*Lee 7

用户robo的regexpabsent方法非常干净,因此我在这里对其进行了充实以便于使用,并通过@assylias和@Olivier的注释进行了改进:

- name: Ensure /tmp/my.conf contains 127.0.0.1
  lineinfile:
    path: /tmp/my.conf
    regexp: '^127\.0\.0\.1.*whatever'
    state: absent
  check_mode: yes
  changed_when: false
  register: out

- debug:
    msg: "Yes, line exists."
  when: out.found

- debug:
    msg: "Line does NOT exist."
  when: not out.found
Run Code Online (Sandbox Code Playgroud)

  • 它可以工作,但不利之处在于,当该行存在时,第一个任务的状态为“已更改”。这可以通过添加`changed_when:false`来解决。 (2认同)
  • 对我来说,最好的解决方案是他的答案,带有 assylias 注释(`changed_when: false`),然后使用 `out.found` 检查是否找到了一行。 (2认同)

VSK*_*VSK 5

使用ansible lineinfile命令,但如果该行不存在,则此命令将使用该行更新该文件.

- lineinfile: dest=/tmp/my.conf line='127.0.0.1' state=present
Run Code Online (Sandbox Code Playgroud)

  • 如果`lineinfile`模块中有state = check,那将会很好 (17认同)

Je.*_*.Go 5

Another way is to use the "replace module" then "lineinfile module".

The algo is closed to the one used when you want to change the values of two variables.

  • First, use "replace module" to detect if the line you are looking for is here and change it with the something else. (Like same line + something at the end).
  • Then if "replace" is true, It means your line is here then replace the new line with a particularity, with the new line looking.
  • Else the line you are looking for is not here.

Example:

# Vars
- name: Set parameters
  set_fact:
    newline      : "hello, i love ansible"
    lineSearched : "hello"
    lineModified : "hello you"

# Tasks
- name: Try to replace the line
  replace:
    dest    : /dir/file
    replace : '{{ lineModified }} '
    regexp  : '{{ lineSearched }}$'
    backup  : yes
  register  : checkIfLineIsHere

- name: Line is here, change it
  lineinfile:
    state   : present
    dest    : /dir/file
    line    : '{{ newline }}'
    regexp  : '{{ lineModified }}$'
  when: checkIfLineIsHere.changed
Run Code Online (Sandbox Code Playgroud)
  • If the file contains "hello", it will become "hello you" then "hello, i love ansible" at the end.
  • If the file content doesn't contain "hello", the file is not modified.

With the same idea, you can do something if the lineSearched is here:

# Vars
- name: Set parameters
  set_fact:
    newline      : "hello, i love ansible"
    lineSearched : "hello"
    lineModified : "hello you"

# Tasks
- name: Try to replace the line
  replace:
    dest    : /dir/file
    replace : '{{ lineModified }} '
    regexp  : '{{ lineSearched }}$'
    backup  : yes
  register  : checkIfLineIsHere

# If the line is here, I want to add something.
- name: If line is here, do something
  lineinfile:
    state   : present
    dest    : /dir/file
    line    : '{{ newline }}'
    regexp  : ''
    insertafter: EOF
  when: checkIfLineIsHere.changed

# But I still want this line in the file, Then restore it
- name: Restore the searched line.
  lineinfile:
    state   : present
    dest    : /dir/file
    line    : '{{ lineSearched }}'
    regexp  : '{{ lineModified }}$'
  when: checkIfLineIsHere.changed
Run Code Online (Sandbox Code Playgroud)
  • If the file contains "hello", the line will still contain "hello" and "hello, i love ansible" at the end.
  • If the file content doesn't contain "hello", the file is not modified.