42

I want to get service like redis-server running status by Ansible.

I know how to use Ansible service module to stop or start system service. But how can I get the current service status?

Promise Preston
  • 24,334
  • 12
  • 145
  • 143
Moxmi
  • 433
  • 1
  • 4
  • 6
  • 1
    Describe your task. You usually just want to tell ansible how you want things to be and don't query anything manually, e.g.: `service: name=httpd state=started`. – Konstantin Suvorov Aug 09 '16 at 10:20
  • @KonstantinSuvorov This is true but the `service` module is missing support for a key use-case: to start/stop/enable/disable a service *if and only if it exists*. For this use case and possibly others, it is necessary to query the status of a service. – StockB Dec 24 '18 at 16:30

11 Answers11

46

You can also use the service_facts module.

Example usage:

- name: collect facts about system services
  service_facts:
  register: services_state

- name: Debug
  debug:
    var: services_state

Example output:

TASK [Debug] ******************************************************
ok: [local] => {
    "services_state": {
        "ansible_facts": {
            "services": {
                "cloud-init-local.service": {
                    "name": "cloud-init-local.service",
                    "source": "systemd",
                    "state": "stopped"
                },
                "firewalld.service": {
                    "name": "firewalld.service",
                    "source": "systemd",
                    "state": "stopped"
                }
            }
        }
    }
}
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
Jay Taylor
  • 13,185
  • 11
  • 60
  • 85
  • How do you get the firewalld.service into a variable? As it contains period, Ansible thinks it is an object, thus running `debug: var: firewall_status.ansible_facts.services.firewalld.service` results in `"VARIABLE IS NOT DEFINED!"` – Maksim Luzik Jan 22 '19 at 11:17
  • 3
    @MaksimLuzik call it like: `var: firewall_status.ansible_facts.services['firewalld.service']` – tstuber Feb 01 '19 at 16:51
  • What if `firewalld` is stored in a variable? – Evren Yurtesen May 10 '20 at 19:41
  • I get `ERROR! 'service_facts' is not a valid attribute for a Play` for this (Ansible 2.9.6) – xjcl Jul 23 '20 at 10:52
  • @xjcl check your indentation...and make sure you have a : after it. service_facts is a module (`ansible.builtin.service_facts:`) – Jeter-work Dec 15 '20 at 20:03
  • Tried this to test but the script got stuck on the service_facts task after gathering facts, what could be the issue and how to debug? Not using a root user. – cnu Mar 08 '21 at 22:48
  • @cnu the issue can be that the machine is too busy. Did you check server stats during the command run. On the other hand, try with become: yes first – Apeasant Jun 09 '21 at 21:56
  • There's no actual need to register the var and then refer to it. After you run `service_facts`, the local var `services` becomes available directly. – DaVince Dec 30 '21 at 14:39
20

Here is a clean sample with ansible.builtin.systemd module.

- name: Get Service Status
  ansible.builtin.systemd:
    name: "postgresql@13-main"
  register: pg_service_status

- debug:
    var: pg_service_status.status.ActiveState

output will be like the one below:

ok: [db01] => {
    "pg_service_status.status.ActiveState": "inactive"
}
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
Sahap Asci
  • 773
  • 7
  • 10
14

Just run the task service: name=httpd state=started with the option --check. This tells you, if the service needs to be started, which means that it is down. If the task shows no change, it is up already.

Example service is down, changed is true, because it needs to be started:

$ ansible -m service -a 'name=rpc/bind state=started' --check host
host | SUCCESS => {
    "changed": true, 
    "msg": "service state changed"
}

Example service is up, changed is false, because nothings need to be done:

$ ansible -m service -a 'name=system-log state=started' --check host
host | SUCCESS => {
    "changed": false, 
    "name": "system-log", 
    "state": "started"
}
ceving
  • 21,900
  • 13
  • 104
  • 178
11

A very short program for checking services using ansible -

- name: checking service status
  hosts: www.linuxfoundation.org
  tasks:
  - name: checking service status
    command: systemctl status "{{ item }}"
    with_items:
    - firewalld
    - httpd
    - vsftpd
    - sshd
    - postfix
    register: result
    ignore_errors: yes
  - name: showing report
    debug:
     var: result
Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
linux.cnf
  • 519
  • 6
  • 7
5

You wouldn't typically do this with Ansible. Ansible should be for declaratively defining how you want a server to look like.

As such you would typically just do something like:

- name: start redis
  service:
    name=redis-server
    state=started
    enabled=yes

You might do things conditionally like this:

- name: restart redis
  service:
    name=redis-server
    state=restarted
    enabled=yes
  when: redis_config.changed

To restart Redis when the configuration has changed but it would be rare to need to check whether a service is running.

In the absolute case that you do need to check whether a service is running (and I would strongly suggest that you think again about your Ansible role/playbook) then you could always shell out:

- name: check redis status
  shell: service redis-service status
ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • I couldn't understand this...please give me some times, i have no using Ansible in this way. – Moxmi Aug 09 '16 at 11:17
  • Per `You wouldn't typically do this with Ansible.` - what tools *should* be used for this? – alex Jan 07 '21 at 15:13
  • 1
    @alex Ansible is designed for declaratively defining the state of infrastructure or a system. You can run ad-hoc commands against an Ansible inventory or another list of hosts using `ansible` directly rather than `ansible-playbook` but that would be a very minor usage of a much more complex tool. Of course if you're already using Ansible then it might help to use the same tool but normally something like that would be checked with something like cluster SSH or better yet, for this use case, a monitoring tool. – ydaetskcoR Jan 07 '21 at 15:54
  • 2
    This isn't true. A situation where you might need this is if you want to start or stop a service which may or may not be installed on all targets. – leggewie Feb 11 '21 at 00:58
  • You should never make a system change just to get status, especially if the system supports production or critical workloads. – Eugene Rosenfeld Aug 01 '23 at 20:32
4

You can say the following:

ansible all -m shell -a "if ! systemctl is-active firewalld; then echo 'inactive' ; fi" -i inventory

If you want to use it in a plyabook, you can try the following:

- name: my playbook example
  hosts: all
  gather_facts: no
  tasks:
  - name: test_task
    shell: "if ! systemctl is-active firewalld; then  echo 'inactive' ; fi"
    register: firewalld_active
    failed_when: False
    changed_when: False

  - debug: var=firewalld_active

  - name: check_value_firewalld
    debug: 
      msg: "'firewalld is inactive' if firewalld_active.stdout=='inactive' else 'service is active' "

Hope it helps!

3

Use command module with service redis-server status and parse stdout.
Or use patched service module.

Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • 2
    ```service redis-server status``` this command will have different result on different OS. – Moxmi Aug 09 '16 at 11:13
  • This patched is better, but i want to achieve it by myself...but i couldn't find where is the entrance – Moxmi Aug 09 '16 at 11:19
  • It is recommended to use modules where available. command/shell should be avoided when possible. – tahoe Sep 05 '22 at 22:57
3

you can do this by ansible AD-HOC command:

$ansible all -m shell -a "service redis-server status"
Alien
  • 15,141
  • 6
  • 37
  • 57
dushyant
  • 349
  • 3
  • 7
1

Personally, I like to have some kind of support Playbooks for getting the status of my services across my environments and to be able to restart them etc.

I'll therefore use on the one side the command module as recommended by Konstantin Suvorov but additionally i'll also check the expected port(s) to ensure that all required ports are up and my service is working as expected. This would look like the following in your case:

- name: verify redis-server service
  command: /usr/sbin/sservice redis-server status
  changed_when: false

- name: verify redis-server is listening on 6379
  wait_for: port=6379 timeout=1

The changed_when is just used because the command module will always set changed to true, although it is just a read-only command.

Michael Aicher
  • 629
  • 12
  • 14
1

If systemctl /service systemd script is not enabled for your service. In my case I was starting zookeeper service manually by executing this command /opt/zookeeper/bin/zkServer.sh start

To make this into ansible

- name: Start Zookeeper service
  command: /opt/zookeeper/bin/zkServer.sh start
  tags:
  - start_zookeeper

- name: Validate whether zookeeper service is running or not 
  shell: netstat -plnt | grep $(ps -ef | grep zookeeper.server.quorum.QuorumPeerMain | grep -v "grep" | awk '{print $2}')
  args:
    executable: /bin/bash
  register: zookeeper_port_status
  retries: 5
  delay: 3
  until: zookeeper_port_status.stdout.find('{{zookeeper_port}}') != -1 
  tags:
  - validate_zookeeeper_service

I am checking zookeeper service status by using netstat and ps -ef linux commands

If zookeeper service is not acquiring port 2181 , then the second ansible module(- name: Validate whether zookeeper service is running or not) will fail, after trying to attempt 5 times(retries: 5)

Zookeeper-Port {{zookeeper_port}}Variable I have defined in my inventory file

Manju N
  • 886
  • 9
  • 14
0

This ansible command should do the trick.

ansible {hostname} -m shell -a "systemctl status redis-server"
agotfrid
  • 507
  • 5
  • 7