Manage Services with Handlers

AnsibleBeginner
Practice Now

Introduction

Handlers are special Ansible tasks that run only when notified by a changed task. They are commonly used for service reloads and restarts.

In this lab, you will deploy a safe demo systemd unit, notify handlers when the unit file changes, and verify that the service is active and enabled.

Create a Service Automation Project

In this step, you will create a project for service automation. This lab uses one local host alias because the service is real system state on the RHEL 10 VM.

cd /home/labex/project
mkdir -p rhce-ansible/{inventory,files,playbooks,reports}
cd rhce-ansible
cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
EOF
cat > inventory/hosts <<'EOF'
[service_hosts]
host ansible_connection=local
EOF

Even with a local connection, the playbook will manage real systemd state on the VM. That is why this lab uses one host alias and become: true later instead of pretending there are several independent service hosts.

Create a Demo systemd Unit File

In this step, you will create the source unit file that Ansible will copy into /etc/systemd/system. The service runs /usr/bin/sleep infinity, so it is safe and easy to verify. Before running commands in this step, return to the Ansible project directory. This keeps the commands stable even when LabEx runs each step separately.

cd /home/labex/project/rhce-ansible
cat > files/rhce-handler-demo.service <<'EOF'
[Unit]
Description=RHCE handler demo service

[Service]
Type=simple
ExecStart=/usr/bin/sleep infinity
Restart=always
RestartSec=1

[Install]
WantedBy=multi-user.target
EOF

This unit is intentionally harmless: it starts a long-running sleep process and restarts it if it exits. The [Install] section makes it possible for Ansible to enable the service for multi-user.target.

sed -n "1,12p" files/rhce-handler-demo.service

Check the ExecStart and WantedBy lines before continuing. If the source unit file is wrong, Ansible will faithfully deploy the wrong service definition.

Write a Playbook with Handlers

In this step, you will write a playbook that copies the unit file and notifies handlers. The meta: flush_handlers task runs pending handlers before the service task, so systemd knows about the new unit. Before running commands in this step, return to the Ansible project directory. This keeps the commands stable even when LabEx runs each step separately.

cd /home/labex/project/rhce-ansible
cat > playbooks/manage-service.yml <<'EOF'
---
- name: Deploy and manage the demo service
  hosts: service_hosts
  become: true
  gather_facts: false
  tasks:
    - name: Install demo systemd unit
      ansible.builtin.copy:
        src: ../files/rhce-handler-demo.service
        dest: /etc/systemd/system/rhce-handler-demo.service
        mode: '0644'
      notify:
        - Reload systemd
        - Restart demo service

    - name: Run handlers before enabling the service
      ansible.builtin.meta: flush_handlers

    - name: Ensure demo service is active and enabled
      ansible.builtin.systemd:
        name: rhce-handler-demo.service
        state: started
        enabled: true

  handlers:
    - name: Reload systemd
      ansible.builtin.systemd:
        daemon_reload: true

    - name: Restart demo service
      ansible.builtin.systemd:
        name: rhce-handler-demo.service
        state: restarted
EOF

The copy task notifies two handlers only when the unit file changes. meta: flush_handlers runs any pending handlers before the systemd task starts and enables the service, which matters because systemd must reload unit files before it knows about a new service.

ansible-playbook playbooks/manage-service.yml --syntax-check

The syntax check should pass before the playbook writes into /etc/systemd/system. It catches indentation mistakes in the task list and in the handlers section without changing service state.

Run the Playbook and Check the Service

In this step, you will run the service playbook. The first run should install the unit, reload systemd, start the service, and enable it for boot. Before running commands in this step, return to the Ansible project directory. This keeps the commands stable even when LabEx runs each step separately.

cd /home/labex/project/rhce-ansible
ansible-playbook playbooks/manage-service.yml | tee reports/service-first-run.txt

The first run should copy the unit file, reload systemd, restart the demo service through the handler, and then ensure the service is enabled. Saving the output lets you review whether the handler path ran.

systemctl is-active rhce-handler-demo.service
systemctl is-enabled rhce-handler-demo.service

is-active checks runtime state for the current boot, while is-enabled checks whether the service is linked into a boot target. RHCE service tasks often require both.

Change the Unit File and Trigger the Handler Again

In this step, you will make a controlled change to the source unit file. When the copy task detects the change, it notifies the handlers again. Before running commands in this step, return to the Ansible project directory. This keeps the commands stable even when LabEx runs each step separately.

cd /home/labex/project/rhce-ansible

The lineinfile module can also edit local files through an ad hoc command. Here it changes only one line in the source unit.

ansible localhost -c local -m ansible.builtin.lineinfile -a 'path=files/rhce-handler-demo.service regexp=^RestartSec= line=RestartSec=3'

This changes the source file, not the installed unit under /etc/systemd/system. The next playbook run should notice the source change, copy the updated unit, and notify the handlers again.

ansible-playbook playbooks/manage-service.yml | tee reports/service-second-run.txt
grep -F RestartSec /etc/systemd/system/rhce-handler-demo.service

The installed unit should now show RestartSec=3. The service should remain active and enabled because the handlers reloaded systemd and restarted the demo service after the file changed.

Summary

You deployed a safe systemd unit, used handlers for systemd reload and service restart, verified active and enabled service state, and triggered the handler with a controlled unit-file change.