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.


