chore: link vault wiki to Gitea
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: "Managing Linux Services: systemd and Ansible"
|
||||
domain: linux
|
||||
category: process-management
|
||||
tags: [systemd, ansible, services, linux, automation]
|
||||
status: published
|
||||
created: 2026-03-08
|
||||
updated: 2026-03-08
|
||||
---
|
||||
|
||||
# Managing Linux Services: systemd and Ansible
|
||||
|
||||
If you're running services on a Linux server, systemd is what you're working with day-to-day — starting, stopping, restarting, and checking on things. For managing services across multiple machines, Ansible is where I've landed. It handles the repetitive stuff so you can focus on what actually matters.
|
||||
|
||||
## The Short Answer
|
||||
|
||||
```bash
|
||||
# Check a service status
|
||||
systemctl status servicename
|
||||
|
||||
# Start / stop / restart
|
||||
sudo systemctl start servicename
|
||||
sudo systemctl stop servicename
|
||||
sudo systemctl restart servicename
|
||||
|
||||
# Enable at boot
|
||||
sudo systemctl enable servicename
|
||||
|
||||
# Disable at boot
|
||||
sudo systemctl disable servicename
|
||||
|
||||
# Reload config without full restart (if supported)
|
||||
sudo systemctl reload servicename
|
||||
```
|
||||
|
||||
## systemd Basics
|
||||
|
||||
systemd is the init system on basically every major Linux distro now. Love it or not, it's what you're using. The `systemctl` command is your interface to it.
|
||||
|
||||
**Checking what's running:**
|
||||
|
||||
```bash
|
||||
# List all active services
|
||||
systemctl list-units --type=service --state=active
|
||||
|
||||
# List failed services (run this when something breaks)
|
||||
systemctl list-units --type=service --state=failed
|
||||
```
|
||||
|
||||
**Reading logs for a service:**
|
||||
|
||||
```bash
|
||||
# Last 50 lines
|
||||
journalctl -u servicename -n 50
|
||||
|
||||
# Follow live (like tail -f)
|
||||
journalctl -u servicename -f
|
||||
|
||||
# Since last boot
|
||||
journalctl -u servicename -b
|
||||
```
|
||||
|
||||
`journalctl` is your friend. When a service fails, go here before you do anything else.
|
||||
|
||||
**Writing a simple service file:**
|
||||
|
||||
Drop a `.service` file in `/etc/systemd/system/` and systemd will pick it up.
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=My Custom App
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=myuser
|
||||
WorkingDirectory=/opt/myapp
|
||||
ExecStart=/opt/myapp/start.sh
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
After creating or editing a service file, reload the daemon before doing anything else:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now myapp
|
||||
```
|
||||
|
||||
## Ansible for Service Management Across Machines
|
||||
|
||||
For a single box, `systemctl` is fine. Once you've got two or more servers doing similar things, Ansible starts paying for itself fast. I've been using it heavily at work and it's changed how I think about managing infrastructure.
|
||||
|
||||
The `ansible.builtin.service` module handles start/stop/enable/disable:
|
||||
|
||||
```yaml
|
||||
- name: Ensure nginx is started and enabled
|
||||
ansible.builtin.service:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: true
|
||||
```
|
||||
|
||||
A more complete playbook pattern:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Manage web services
|
||||
hosts: webservers
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Install nginx
|
||||
ansible.builtin.package:
|
||||
name: nginx
|
||||
state: present
|
||||
|
||||
- name: Start and enable nginx
|
||||
ansible.builtin.service:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Reload nginx after config change
|
||||
ansible.builtin.service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
```
|
||||
|
||||
Run it with:
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.ini manage-services.yml
|
||||
```
|
||||
|
||||
## Gotchas & Notes
|
||||
|
||||
- **daemon-reload is mandatory after editing service files.** Forgetting this is the most common reason changes don't take effect.
|
||||
- **`restart` vs `reload`:** `restart` kills and relaunches the process. `reload` sends SIGHUP and asks the service to re-read its config without dropping connections — only works if the service supports it. nginx and most web servers do. Not everything does.
|
||||
- **Ansible's `restarted` vs `reloaded` state:** Same distinction applies. Use `reloaded` in Ansible handlers when you're pushing config changes to a running service.
|
||||
- **Checking if a service is masked:** A masked service can't be started at all. `systemctl status servicename` will tell you. Unmask with `sudo systemctl unmask servicename`.
|
||||
- **On Fedora/RHEL:** SELinux can block a custom service from running even if systemd says it started fine. If you see permission errors in `journalctl`, check `ausearch -m avc` for SELinux denials.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[wsl2-instance-migration-fedora43]]
|
||||
- [[tuning-netdata-web-log-alerts]]
|
||||
Reference in New Issue
Block a user