| |

LFCS 61 ๐Ÿง systemd โ€” Managing Services

โฑ๏ธ Estimated read: 15 min | |

The LFCS exam tests systemd at the operational level: can you start a service, make it persist across reboots, verify its status, and read its logs? The commands are not complicated individually, but the exam is performance-based on a live system, and the most common failure is not a wrong commandโ€”it is a command that works in the current session but does not survive a reboot. The systemctl enable versus systemctl start distinction is the single most tested concept in this domain, and the --now flag that combines them exists precisely because forgetting the enable step is the classic trap .

systemd organizes resources into units, and the service unit is the type that manages daemons. A service unit’s configuration file ends in .service and lives in directories like /usr/lib/systemd/system for package-installed units or /etc/systemd/system for administrator-created ones . The systemctl command is the interface: it starts, stops, enables, disables, and inspects units. The journalctl command reads the logs that systemd’s journal collects, and it filters by unit with the -u flag.

This chapter covers the service unit lifecycle, the enable/start distinction and the --now shorthand, status inspection and log reading, custom unit file creation, and the exam traps that turn a working command into a failed task. It assumes a running systemd-based Linux system and familiarity with basic command-line operations.

Key point: start runs a service now; enable makes it start at boot. The exam grader reboots the machine, so a service that was started but not enabled fails the task. systemctl enable --now <service> does both in one command, and it is the correct answer whenever the task says “start automatically at boot and start now.”


Why systemd service management is an exam domain

The exam is performance-based, not multiple-choice. The LFCS tests on a live system, and service configuration is weighted at roughly 20% of the exam alongside essential commands . A candidate who knows the commands but does not verify persistence will pass the command execution and fail the task. The exam scenarios are written to test operational judgment, not memorization: “A service should start automatically at boot and start now” is a scenario that distinguishes candidates who understand the enable/start distinction from those who do not .

The enable/start distinction is the primary trap. systemctl start nginx starts the service in the current session. It does not create the symlinks that cause systemd to start the service during boot. systemctl enable nginx creates those symlinks but does not start the service. The exam grader reboots the machine after the candidate finishes. A service that was started but not enabled is not running after the reboot, and the task fails . The --now flag exists to prevent this exact error: systemctl enable --now nginx enables and starts in one command .

Logs are part of the service lifecycle. When a service fails to start, the status output shows the last few log lines, but the full journal requires journalctl -u <service>. The -f flag follows new output, and -n <count> limits the number of lines. The exam tests the ability to diagnose why a service failed, not just whether it is running .

Custom unit files test understanding of the configuration model. A task may ask the candidate to configure an application as a service. This requires creating a .service file in /etc/systemd/system, defining the [Unit], [Service], and [Install] sections, running systemctl daemon-reload, and then enabling and starting the service. The [Install] section with WantedBy=multi-user.target is what makes enable work; without it, the service cannot be enabled .

The trade-off. systemd’s model is more verbose than the legacy service command. A single systemctl enable --now nginx replaces two separate commands and a symlink check. The verbosity is the price of the dependency management and parallel startup that systemd provides. The exam tests the verbosity because that is what production systems use.


a. The service lifecycle: start, stop, restart, reload

The basic service operations are direct: systemctl start <service> starts a stopped service, systemctl stop <service> stops a running one, and systemctl restart <service> stops and starts. systemctl reload <service> asks the service to reload its configuration without a full restart, but this only works if the service supports it; a service that does not support reload will return an error or ignore the command .

# Start the nginx service now.
sudo systemctl start nginx

# Stop it.
sudo systemctl stop nginx

# Restart: stop and start, applying configuration changes.
sudo systemctl restart nginx

# Reload: re-read configuration without dropping connections,
# if the service supports it.
sudo systemctl reload nginx

The condrestart (conditional restart) command restarts a service only if it is currently running. This is safer in scripts where the service may or may not be active, because it does not start a stopped service as a side effect. try-restart is an alias for the same behavior .

systemctl status <service> is the inspection command. It shows the service’s loaded state, active state, main PID, and the most recent log lines. The output distinguishes between active (running), inactive (dead), and failed. A service that exited with a non-zero status shows failed and the exit code .

# Check status: active state, PID, recent logs.
systemctl status nginx

The status output is a summary. For the full journal, journalctl -u nginx shows all log entries for the unit, and journalctl -u nginx -f follows new entries in real time. The -n 50 flag limits to the last 50 lines .


b. Enable and disable: persistence across reboots

systemctl enable <service> creates the symbolic links that cause systemd to start the service when the system reaches the target specified in the unit’s [Install] section. It does not start the service in the current session. systemctl disable <service> removes those symlinks. The is-enabled command reports whether the symlinks exist, and is-active reports whether the service is currently running .

# Enable at boot and start now, in one command.
sudo systemctl enable --now nginx

# Verify both states.
systemctl is-enabled nginx   # enabled
systemctl is-active nginx    # active

The --now flag is the exam-safe pattern. When a task says “ensure the service starts automatically at boot and is running now,” enable --now is the command that satisfies both requirements atomically. Using enable and start as separate commands works, but the combined form is less error-prone and directly maps to the task description .

The disable command does not stop a running service. A service can be running but disabled, or stopped but enabled. The two states are independent: enable controls boot behavior, start controls current behavior. The exam may test this independence by asking for a service that is running but not enabled, or enabled but not running.

Masking is a stronger form of disabling. systemctl mask <service> creates a symlink to /dev/null, preventing the service from being started at allโ€”even manually, and even as a dependency of another service. unmask reverses it. This is used when a service must be prevented from starting for security or policy reasons, not merely disabled at boot.


c. Creating a custom service unit

A custom service unit is a file in /etc/systemd/system/ with a .service extension. The minimal unit has three sections: [Unit] for metadata and dependencies, [Service] for the execution command and restart policy, and [Install] for the boot target that enable uses .

# /etc/systemd/system/my_app.service
[Unit]
Description=My Python Web Application
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/code/my_app.py
Restart=always
User=appuser

[Install]
WantedBy=multi-user.target

ExecStart is the command that runs the service. Restart=always configures systemd to restart the process if it exits, which provides basic supervision. User=appuser runs the service as a non-root user. The After=network.target directive in [Unit] ensures the service starts after networking is available, which is important for applications that bind to a network port .

After creating or modifying a unit file, systemctl daemon-reload is required. systemd caches unit file contents, and it does not notice changes until the cache is refreshed. Without daemon-reload, systemctl start uses the old configuration, and the new service may fail with a “unit not found” error even though the file exists .

# Reload systemd's unit cache after creating or editing a unit.
sudo systemctl daemon-reload

# Enable and start the custom service.
sudo systemctl enable --now my_app

# Verify.
systemctl status my_app

The [Install] section is what makes enable possible. WantedBy=multi-user.target tells systemd that when the system reaches the multi-user target (the normal non-graphical boot state), it should start this service. Without an [Install] section, the service can be started manually but cannot be enabled, and the systemctl enable command returns an error .


Complete Example Session

# ============================================
# PART 1: START AND VERIFY
# ============================================
# Start the service now.
sudo systemctl start nginx

# Verify it is running.
systemctl is-active nginx   # active
systemctl status nginx      # shows PID and recent logs

# ============================================
# PART 2: THE ENABLE TRAP
# ============================================
# This starts nginx but does NOT survive a reboot.
sudo systemctl start nginx

# This makes it survive a reboot but does NOT start it now.
sudo systemctl enable nginx

# This does both, and is the exam-safe answer.
sudo systemctl enable --now nginx

# ============================================
# PART 3: STOP AND DISABLE
# ============================================
# Stop the running service.
sudo systemctl stop nginx

# Prevent it from starting at boot.
sudo systemctl disable nginx

# Verify both states.
systemctl is-active nginx    # inactive
systemctl is-enabled nginx   # disabled

# ============================================
# PART 4: LOGS
# ============================================
# View all journal entries for the unit.
journalctl -u nginx

# Follow new entries in real time.
journalctl -u nginx -f

# Last 50 lines plus follow.
journalctl -u nginx -n 50 -f

# ============================================
# PART 5: CREATE A CUSTOM SERVICE
# ============================================
# Create the unit file.
sudo tee /etc/systemd/system/my_app.service <<'EOF'
[Unit]
Description=My Application
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/code/my_app.py
Restart=always

[Install]
WantedBy=multi-user.target
EOF

# Reload systemd to pick up the new unit.
sudo systemctl daemon-reload

# Enable and start.
sudo systemctl enable --now my_app

# Verify.
systemctl status my_app

# ============================================
# PART 6: EDIT AN EXISTING UNIT SAFELY
# ============================================
# Use systemctl edit for drop-in overrides.
# Do not edit files in /usr/lib/systemd/system directly.
sudo systemctl edit my_app

# The editor opens a drop-in file at:
# /etc/systemd/system/my_app.service.d/override.conf
# Add or override directives, save, then reload.
sudo systemctl daemon-reload
sudo systemctl restart my_app

# ============================================
# PART 7: TROUBLESHOOT A FAILED SERVICE
# ============================================
# Check status for exit code and recent logs.
systemctl status my_app

# Read full journal.
journalctl -u my_app -n 100

# Common causes:
# - Wrong path in ExecStart
# - Missing User if service needs specific permissions
# - No [Install] section (cannot enable)
# - daemon-reload not run after creating unit

# ============================================
# PART 8: LIST SERVICES
# ============================================
# List running services.
systemctl list-units --type=service

# List all installed unit files, enabled or not.
systemctl list-unit-files

# Find failed units.
systemctl --failed

# ============================================
# PART 9: MASK TO PREVENT START
# ============================================
# Disable is not enough if the service is pulled in
# as a dependency. Mask prevents all starts.
sudo systemctl mask nginx

# Unmask to restore.
sudo systemctl unmask nginx

# ============================================
# PART 10: THE EXAM CHECKLIST
# ============================================
# For any service task, verify:
# 1. systemctl is-active <service>    โ†’ active
# 2. systemctl is-enabled <service>   โ†’ enabled
# 3. If custom unit: daemon-reload was run
# 4. If service fails: journalctl -u <service>
# The grader reboots. Enabled is not optional.

Quick Reference

Service Control Commands

CommandEffectSurvives Reboot
systemctl start <svc>Start nowNo
systemctl stop <svc>Stop nowNo
systemctl restart <svc>Stop and startNo
systemctl reload <svc>Reload config (if supported)No
systemctl enable <svc>Start at bootYes (but not now)
systemctl disable <svc>Do not start at bootNo
systemctl enable --now <svc>Enable and startYes

Status Inspection

CommandReports
systemctl status <svc>Active state, PID, recent logs
systemctl is-active <svc>active or inactive
systemctl is-enabled <svc>enabled or disabled
journalctl -u <svc>All journal entries for unit
journalctl -u <svc> -fFollow new entries
journalctl -u <svc> -n 50 -fLast 50 lines + follow

Custom Unit File Sections

SectionPurposeKey Directives
[Unit]Metadata, dependenciesDescription, After
[Service]ExecutionExecStart, Restart, User
[Install]Boot target for enableWantedBy=multi-user.target

Exam Traps

TrapSymptomFix
Start without enableService dead after rebootenable --now
Enable without startService not running nowenable --now
No daemon-reloadUnit not found after creationsystemctl daemon-reload
Missing [Install]enable failsAdd WantedBy
Editing /usr/libChanges lost on package updateUse systemctl edit

Best Practices

โœ… Do This:

# Enable and start in one command.                            // โœ…
sudo systemctl enable --now nginx

# Reload after creating or editing a unit file.              // โœ…
sudo systemctl daemon-reload

# Use systemctl edit for overrides.                          // โœ…
sudo systemctl edit my_app

# Read the journal when a service fails.                     // โœ…
journalctl -u my_app -n 100

# Verify both active and enabled states.                     // โœ…
systemctl is-active my_app && systemctl is-enabled my_app

โŒ Don’t Do This:

# Start without enabling for a "start at boot" task.         // โŒ
sudo systemctl start nginx  # Dead after reboot.

# Skip daemon-reload after creating a unit.                  // โŒ
sudo systemctl start my_app  # "Unit not found."

# Edit files in /usr/lib/systemd/system directly.            // โŒ
# Changes overwritten by package updates. Use systemctl edit.

# Assume reload works for every service.                     // โŒ
# Some services do not support reload; use restart.

Common Pitfalls

PitfallWhy It HappensFix
Service not running after rebootStarted but not enabledenable --now
“Unit not found” after creating filedaemon-reload not runRun it before start
Cannot enable custom serviceMissing [Install] sectionAdd WantedBy=multi-user.target
Status shows failed but no errorLogs are in journal, not statusjournalctl -u <svc>
Configuration change ignoredService not restarted or reloadedrestart or reload

Real-World Examples

1. Enable and Start Nginx

sudo systemctl enable --now nginx

2. Check Both States

systemctl is-active nginx && systemctl is-enabled nginx

3. Create Custom Service

sudo tee /etc/systemd/system/app.service <<'EOF'
[Unit]
Description=App
[Service]
ExecStart=/usr/bin/app
[Install]
WantedBy=multi-user.target
EOF

4. Reload After Unit Change

sudo systemctl daemon-reload

5. Follow Service Logs

journalctl -u app -f

6. Last 50 Log Lines

journalctl -u app -n 50

7. Safe Override

sudo systemctl edit app

8. List Failed Units

systemctl --failed

9. Mask a Service

sudo systemctl mask nginx

10. Conditional Restart

sudo systemctl condrestart app  # Only if running.

Visual

Enable vs Start

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ENABLE vs START                            โ”‚
โ”‚                                              โ”‚
โ”‚  systemctl start nginx                       โ”‚
โ”‚    โ†’ Runs now                                โ”‚
โ”‚    โ†’ Creates no symlinks                     โ”‚
โ”‚    โ†’ Reboot: NOT running                     โ”‚
โ”‚                                              โ”‚
โ”‚  systemctl enable nginx                      โ”‚
โ”‚    โ†’ Creates symlink in target.wants/        โ”‚
โ”‚    โ†’ Does NOT run now                        โ”‚
โ”‚    โ†’ Reboot: running                         โ”‚
โ”‚                                              โ”‚
โ”‚  systemctl enable --now nginx                โ”‚
โ”‚    โ†’ Creates symlinks                        โ”‚
โ”‚    โ†’ Starts now                              โ”‚
โ”‚    โ†’ Reboot: running                         โ”‚
โ”‚                                              โ”‚
โ”‚  The exam grader reboots.                    โ”‚
โ”‚  Enable is not optional.                     โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Service Unit File Structure

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  my_app.service                              โ”‚
โ”‚                                              โ”‚
โ”‚  [Unit]                                      โ”‚
โ”‚    Description=My Application                โ”‚
โ”‚    After=network.target                      โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ”‚ metadata, dependencies             โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  [Service]                                   โ”‚
โ”‚    ExecStart=/usr/bin/python3 /opt/app.py    โ”‚
โ”‚    Restart=always                            โ”‚
โ”‚    User=appuser                              โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ”‚ execution model                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  [Install]                                   โ”‚
โ”‚    WantedBy=multi-user.target                โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ”‚ enable target                      โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  systemctl enable creates symlink here.      โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Troubleshooting Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SERVICE FAILS TO START                      โ”‚
โ”‚                                              โ”‚
โ”‚  systemctl status my_app                     โ”‚
โ”‚       โ”‚                                      โ”‚
โ”‚       โ”œโ”€โ”€ "Unit not found"                   โ”‚
โ”‚       โ”‚     โ†’ daemon-reload not run          โ”‚
โ”‚       โ”‚                                      โ”‚
โ”‚       โ”œโ”€โ”€ "Failed with result 'exit-code'"   โ”‚
โ”‚       โ”‚     โ†’ journalctl -u my_app           โ”‚
โ”‚       โ”‚     โ†’ check ExecStart path           โ”‚
โ”‚       โ”‚                                      โ”‚
โ”‚       โ””โ”€โ”€ "inactive (dead)"                  โ”‚
โ”‚             โ†’ systemctl start my_app         โ”‚
โ”‚             โ†’ check journal for error        โ”‚
โ”‚                                              โ”‚
โ”‚  Always read the journal, not just status.   โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Exam Checklist

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SERVICE TASK VERIFICATION                   โ”‚
โ”‚                                              โ”‚
โ”‚  Task: "Start nginx and ensure it            โ”‚
โ”‚         starts on boot."                     โ”‚
โ”‚                                              โ”‚
โ”‚  1. sudo systemctl enable --now nginx        โ”‚
โ”‚                                              โ”‚
โ”‚  2. Verify active:                           โ”‚
โ”‚     systemctl is-active nginx โ†’ active       โ”‚
โ”‚                                              โ”‚
โ”‚  3. Verify enabled:                          โ”‚
โ”‚     systemctl is-enabled nginx โ†’ enabled     โ”‚
โ”‚                                              โ”‚
โ”‚  4. If custom unit:                          โ”‚
โ”‚     sudo systemctl daemon-reload             โ”‚
โ”‚                                              โ”‚
โ”‚  5. If failure:                              โ”‚
โ”‚     journalctl -u nginx -n 50                โ”‚
โ”‚                                              โ”‚
โ”‚  Both checks must pass.                      โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
StartRuns service now, no boot persistence
EnableBoot persistence, no current start
enable --nowBoth in one command
Statussystemctl status, is-active, is-enabled
Logsjournalctl -u <svc>, -f follow, -n limit
Custom unit location/etc/systemd/system/<name>.service
Required sections[Unit], [Service], [Install]
daemon-reloadRequired after unit creation or edit
[Install] targetWantedBy=multi-user.target
MaskPrevents all starts, stronger than disable

Key takeaways:

  • start runs now; enable persists at boot. The exam reboots the machine. A service that was started but not enabled fails the task. systemctl enable --now <service> satisfies both requirements in one command .
  • daemon-reload is mandatory after creating or editing a unit file. systemd caches unit contents. Without the reload, systemctl start uses the old configuration or reports “unit not found” .
  • The [Install] section is what makes enable work. WantedBy=multi-user.target tells systemd which target should pull in the service. Without it, the service can be started manually but cannot be enabled .
  • journalctl -u <service> is the diagnostic tool. Status shows a summary; the full log shows the error. -f follows, -n limits .
  • Use systemctl edit for overrides, not direct edits to /usr/lib. Drop-in files in /etc/systemd/system/<unit>.d/ survive package updates .
  • is-active and is-enabled are the verification commands. Both must return the expected state after a service task. Checking only one is incomplete.

Remember: systemd service management on the LFCS is a test of operational completeness, not command memorization. The commands are simple: start, stop, enable, disable, status, journalctl. The trap is the gap between “works now” and “works after reboot.” The exam grader reboots. enable --now closes the gap. Custom units add a second trap: the daemon-reload that refreshes the cache and the [Install] section that makes enable possible. Verify both statesโ€”active and enabledโ€”before considering a service task complete.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!