【问题标题】:Using Ansible to stop service that might not exist使用 Ansible 停止可能不存在的服务
【发布时间】:2021-01-21 18:54:55
【问题描述】:

我正在使用 Ansible 2.6.1

我正在尝试确保某些服务未在目标主机上运行。 问题是某些主机上可能根本不存在该服务。如果是这种情况,Ansible 由于缺少服务而失败并出现错误。服务由Systemd 运行。

使用服务模块:

  - name: Stop service
    service:
      name: '{{ target_service }}'
      state: stopped

失败并出现错误Could not find the requested service SERVICE: host

尝试使用命令模块:

 - name: Stop service
   command: service {{ target_service }} stop

给出错误:Failed to stop SERVICE.service: Unit SERVICE.service not loaded.

我知道我可以使用ignore_errors: yes,但它也可能隐藏真正的错误。

另一种解决方案是有 2 个任务。一个检查服务是否存在,另一个只在第一个任务找到服务但感觉很复杂时运行。

是否有更简单的方法来确保服务停止并在服务不存在时避免错误?

【问题讨论】:

  • 这是XY problem。更好地专注于了解什么在哪里运行。
  • 这不是 XY 问题。详细信息超出了此问题的范围,但在这种情况下无法预测服务在哪些主机上运行。 (运行该服务的主机数量以及应该运行该服务的主机数量取决于主机负载和使用该服务的客户端数量动态决定。)为了安全地运行维护操作,所述服务不能运行。无论服务是否存在,维护操作都需要在所有主机上运行,​​因此确保服务没有运行任何目标主机是有意义的。
  • 根据您的服务,您可以创建一个任务来检查该服务的软件包是否已安装,然后仅在该服务存在时才停止该服务。
  • 确保服务已停止并不断停止的最简单方法是卸载它。

标签: ansible


【解决方案1】:

我正在使用以下步骤:

- name: Get the list of services
  service_facts:

- name: Stop service
  systemd:
    name: <service_name_here>
    state: stopped
  when: "'<service_name_here>.service' in services"

service_facts 可以在收集事实阶段调用一次。

【讨论】:

    【解决方案2】:

    下面会将模块输出注册到service_stop;如果模块执行的标准输出不包含"Could not find the requested service" 并且服务未能根据返回码停止,则模块执行将失败。由于您没有包含整个堆栈跟踪,我假设您发布的错误在标准输出中,您可能需要根据您的错误稍作更改。

    - name: Stop service
      register: service_stop
      failed_when: 
        - '"Could not find the requested service" not in service_stop.stdout'
        - service_stop.rc != 0
      service:
        name: '{{ target_service }}'
        state: stopped
    

    【讨论】:

      【解决方案3】:

      恕我直言,没有更简单的方法可以确保停止服务。 Ansible service 模块不检查服务的存在。需要 (1) 一个以上的任务,或 (2) 检查服务是否存在的命令。该命令将是特定于操作系统的。例如对于 FreeBSD

      command: "service -e | grep {{ target_service }} && service {{ target_service }} stop"
      

      【讨论】:

        【解决方案4】:

        与 Vladimir 的解决方案相同,但适用于 Ubuntu (systemd) 并具有更好的状态处理:

        - name: restart {{ target_service }} if exists
          shell: if systemctl is-enabled --quiet {{ target_service }}; then systemctl restart {{ target_service }} && echo restarted ; fi
          register: output
          changed_when: "'restarted' in output.stdout"
        

        它产生 3 种状态:

        • 服务不存在或被禁用——ok
        • 服务存在并重新启动 — changed
        • 服务存在且重启失败 — failed

        【讨论】:

          【解决方案5】:

          当服务模块出现故障时,检查需要停止的服务是否安装完毕。这类似于this answer,但除非必要,否则避免了相当长的服务事实收集。

          - name: Stop a service
            block:
              - name: Attempt to stop the service
                service:
                  name:  < service name >
                  state: stopped
            rescue:
              - name: Get the list of services
                service_facts:
          
              - name: Verify that Nagios is not installed
                assert:
                  that:
                    - "'< service name >.service' not in services"
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-31
            相关资源
            最近更新 更多