Ansible 剧本中的 'not to run multiple times' command/shell 如何执行任务

How 'not to run multiple times' command/shell task in Ansible playbook

我在 Ansible 中有一项任务是通过 RubyGems 选项安装 SASS 实用程序,它运行良好,没有任何问题。如果我再次重新 运行 同一个剧本,它会再次尝试重新安装此实用程序。

在这种情况下,如何在 Ansible 剧本中使用命令或 shell 用法 运行 一次。我已经通过使用 'when' 选项以某种方式处理了它而不是 运行 安装,但需要更好的指导 logic/implementation

任务信息:

- name: Install SASS packages by using npm utility.
  command: /usr/bin/npm install -g sass

为了消除在 Ansible 剧本中重新 运行 执行上述命令任务,我使用了以下验证逻辑并添加了 'when' 选项,如下所示。这样可以吗,还是我们有更好的方法来处理这个问题?

- name: Validation of SASS packages availability.
  shell: /usr/local/bin/sass --version
  register: result
- debug:
    msg: "{{ result.stdout }}"

- name: Install SASS packages by using npm utility.
  command: /usr/bin/npm install -g sass
  when: "'No such file or directory' in result.stdout"

结果:

TASK [mean-stack : Validation of SASS packages availability.] ************************************************************************************
changed: [linuxosdev003.local.lab]

TASK [mean-stack : debug] ************************************************************************************************************************
ok: [linuxosdev003.local.lab] => {
    "msg": "1.47.0 compiled with dart2js 2.15.1"
}

TASK [mean-stack : Install SASS packages by using npm utility.] **********************************************************************************
skipping: [linuxosdev003.local.lab]

PLAY RECAP ***************************************************************************************************************************************
linuxosdev003.local.lab    : ok=6    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

如果你想要一个幂等的剧本,你应该尽可能避免使用 commandshell。特别是你的例子 - 删除 sass 并尝试你的剧本。它应该失败。检查文件是否存在

- name: "Check, if file exists"
  stat:
    path: "/usr/local/bin/sass"
  register: sass_installed

但是 - 正如已经评论过的 - 使用 ansible 模块来安装 NPM 包,就像你对系统包所做的那样(packageyumapt)或 Python 模块(pip)。该模块在最新的 RedHat release 2.9 中也可用 https://docs.ansible.com/ansible/2.9/modules/npm_module.html 并且应该很简单:

- name: "Install NPM package: sass"
  npm:
    name: "sass"

如果你需要安装多个 NPM 包,你可以遍历它们

- name: "Install NPM packages"
  npm:
    name: "{{ item }}"
  loop:
    - "package1"
    - "package2"

正如@β.εηοιτ.βε 和@TRW 已经提到的,使用模块将消除此类检查的需要。

但是,如果只是检查路径是否存在那么简单,那么command module本身就可以这样使用:

- name: Install SASS packages by using npm utility.
  command:
    cmd: /usr/bin/npm install -g sass
    creates: /usr/local/bin/sass

这等于您的 when 条件,即当 creates 中给定的路径不存在时,命令将 运行。

如果包管理器可用于任务,我更喜欢@β.εηοιτ.βε 和@TRW 的解决方案,有时可能需要留在 shell 模块上。对于这种情况,我使用与原始问题类似的方法。

---
- hosts: test.example.com
  become: no
  gather_facts: no

  tasks:

  - name: Gather installed Java version, if there is any
    shell:
      cmd: java -version 2>&1 | head -1 | cut -d '"' -f 2
    register: result
    check_mode: false
    changed_when: false
    failed_when: result.rc != 0 and result.rc != 127

  - name: Set default version, if there is no
    set_fact:
      result:
        stdout_lines: "0.0.0_000"
    when: "'command not found' in result.stdout"
    check_mode: false

  - name: Report result
    debug:
      msg: "{{ result.stdout_lines }}"
    check_mode: false

根据安装的版本,如有必要,将调用安装程序或更新程序来安装或更新到最新版本。

感谢

  • Why does Java version go to stderr?