Проверьте, существует ли служба с Ansible

У меня есть плейбук Ansible для развертывания приложения Java в качестве демона init.d.

Поскольку я новичок как в Ansible, так и в Linux, у меня возникают проблемы с условным выполнением задач на хосте в зависимости от статуса хоста.

А именно, у меня есть несколько хостов, на которых служба уже присутствует и работает, где я хочу остановить ее, прежде чем делать что-либо еще. А потом могут появиться новые хосты, у которых еще нет услуги. Поэтому я не могу просто использовать service: name={{service_name}} state=stopped, потому что это не сработает на новых хостах.

Как я могу этого добиться? Вот что у меня есть на данный момент:

  - name: Check if Service Exists
    shell: "if chkconfig --list | grep -q my_service;   then echo true;   else echo false; fi;"
    register: service_exists

# This should only execute on hosts where the service is present
  - name: Stop Service
    service: name={{service_name}} state=stopped
    when: service_exists
    register: service_stopped

# This too
  - name: Remove Old App Folder
    command: rm -rf {{app_target_folder}}
    when: service_exists

# This should be executed on all hosts, but only after the service has stopped, if it was present
  - name: Unpack App Archive
    unarchive: src=../target/{{app_tar_name}} dest=/opt

person EagleBeak    schedule 19.05.2015    source источник


Ответы (7)


См. Модуль service_facts, новый в Ansible 2.5. .

- name: Populate service facts
  service_facts:
- debug:
    msg: Docker installed!
  when: "'docker' in services"
person Aidan Feldman    schedule 10.07.2018
comment
Это кажется многообещающим, но его результат кажется несовместимым с ожидаемым именем службы, по крайней мере, для проверки службы telnet.socket, которая отображается в ansible_facts.services как [email protected]. - person StockB; 21.11.2018
comment
Факты о сервисах собираются в hostvars [$ host] ['services'] - person HermanTheGermanHesse; 02.06.2019
comment
Использование when: "'docker' in services" не дает результата - собранные факты индексируются с использованием полного имени (docker.service) вместо docker. Может зависеть от платформы, но, по крайней мере, в CentOS факты используют только полные имена. - person jso; 27.11.2019
comment
Есть важное замечание о том, как получить доступ к именам служб на странице соответствующего модуля, которая Стоит отметить. Имея это в виду, я успешно использовал: when: ansible_facts.services['service-name.service'] is defined в Ubuntu - person Ian Gibbs; 28.04.2020
comment
Кажется, что service_facts работает медленно, я предпочитаю проверять наличие служебного файла - person abzarak; 20.10.2020

Конечно, я мог бы просто проверить, существует ли сценарий оболочки в /etc/init.d. Вот что у меня получилось:

  - name: Check if Service Exists
    stat: path=/etc/init.d/{{service_name}}
    register: service_status

  - name: Stop Service
    service: name={{service_name}} state=stopped
    when: service_status.stat.exists
    register: service_stopped
person EagleBeak    schedule 19.05.2015
comment
вы также можете использовать ignore_errors, особенно с регистром, чтобы обнаружить это. - person tedder42; 19.05.2015
comment
Да, я избегал ignore_errors, потому что боялся ложных негативов из-за опечаток и тому подобного. Также я пытаюсь убедить свою команду вкладывать средства в автоматизацию управления конфигурациями и не хочу, чтобы они в первую очередь выглядели как какой-то взлом. :) - person EagleBeak; 19.05.2015
comment
решение также работает на ubuntu и, вероятно, должно работать на большинстве дистрибутивов Linux. - person ryantuck; 28.06.2015
comment
ansible также добавляет флаг must_exist в служебный модуль в версии 2.0, что устраняет необходимость в первой проверке: docs.ansible.com/service_module.html - person ryantuck; 28.06.2015
comment
@RyanTuck нет параметра must_exist, указанного на странице, на которую вы указали ссылку. И теперь 2.0 официально выпущена. - person aef; 28.02.2016
comment
@aef, оказалось, что он был снова удален перед выпуском, см. здесь: github.com/ansible/ ansible / issues / 13259 - person HansHarhoff; 27.03.2017
comment
Это только частично сработало для меня на Mint 18.2. Некоторые из моих сервисов systemd имели сценарии инициализации, но не все из них, остерегайтесь этого и проверьте, используете ли этот метод - person ddrake12; 30.04.2018
comment
К вашему сведению: в ubuntu вы должны заглянуть в / etc / systemd / system - person abzarak; 20.10.2020
comment
В дополнение к комментариям @ darkwing и @ abzarak: вместо проверки оболочки сценария инициализации можно напрямую проверить /etc/systemd/system/{{service_name}}.service. Многие новые системы и выпуски пакетов отказываются от сценариев оболочки SysVinit. - person ncoghlan; 27.04.2021

Было бы хорошо, если бы модуль «служба» мог обрабатывать ошибки «нераспознанной службы».

Это мой подход, использующий команду service вместо проверки сценария инициализации:

- name: check for apache
  shell: "service apache2 status"
  register: _svc_apache
  failed_when: >
    _svc_apache.rc != 0 and ("unrecognized service" not in _svc_apache.stderr)

- name: disable apache
  service: name=apache2 state=stopped enabled=no
  when: "_svc_apache.rc == 0"
  • проверьте код выхода «статус службы» и примите код выхода 0, если вывод содержит «нераспознанную службу»
  • если код выхода был 0, эта служба установлена ​​(остановлена ​​или запущена)
person Florian    schedule 17.03.2016

Я изменил ответ Флориана, чтобы использовать только код возврата команды service (это работало на Mint 18.2)

- name: Check if Logstash service exist
  shell: service logstash status 
  register: logstash_status
  failed_when: not(logstash_status.rc == 3 or logstash_status.rc == 0)

- name: Check if Logstash service exist
  service:
    name: logstash
    state: stopped 
  when: logstash_status.rc == 0
person ddrake12    schedule 30.04.2018

Другой подход для systemd (от Jakuje):

- name: Check if cups-browsed service exists
  command: systemctl cat cups-browsed
  check_mode: no
  register: cups_browsed_exists
  changed_when: False
  failed_when: cups_browsed_exists.rc not in [0, 1]

- name: Stop cups-browsed service
  systemd:
    name: cups-browsed
    state: stopped 
  when: cups_browsed_exists.rc == 0
person sourcejedi    schedule 10.09.2019

Мои несколько центов. Тот же подход, что и выше, но для кубернетов

Проверьте, запущена ли служба кублете

- name: "Obtain state of kublet service"
  command: systemctl status kubelet.service
  register: kubelet_status
  failed_when: kubelet_status.rc > 3

Отображать сообщение об отладке, если служба kublet не запущена

- debug:
    msg: "{{ kubelet_status.stdout }}"
  when: "'running' not in kubelet_status.stdout"
person Lukasz Dynowski    schedule 15.02.2019
comment
К сожалению, этот подход не будет работать, если служба не существует (и это то, о чем просил OP). С вашим кодом вы все равно получите Unit kubelet.service could not be found ошибку. - person jso; 27.11.2019
comment
@jso Вы правы. Это решение предполагает, что служба установлена ​​на хосте, поскольку в вопросах говорится: У меня есть несколько хостов, на которых служба уже присутствует и работает, но не работает, когда служба отсутствует. Таким образом, я проголосую за ваш комментарий :) - person Lukasz Dynowski; 27.11.2019

Таким образом, использование только служебного модуля сработало для нас:

- name: Disable *service_name*
  service:
    name: *service_name*
    enabled: no
    state: stopped
  register: service_command_output
  failed_when: >
    service_command_output|failed
    and 'unrecognized service' not in service_command_output.msg
    and 'Could not find the requested service' not in service_command_output.msg
person Paul Dubuc    schedule 26.05.2021