Skip to main content

systemd Basics: Starting, Stopping and Enabling Linux Services

Media systemd Basics Starting, Stopping and Enabling Linux Services

Many Linux applications run quietly in the background.

Web servers listen for connections, databases process requests, network services manage connectivity and scheduled tools perform maintenance without opening a desktop window. On most modern Linux distributions, these background services are managed by systemd.

When a service fails, starts unexpectedly or does not launch after a reboot, systemctl is usually the first tool to use.

The essential commands are straightforward:

sudo systemctl start service-name

sudo systemctl stop service-name

sudo systemctl restart service-name

sudo systemctl enable service-name

sudo systemctl disable service-name

sudo systemctl status service-name

However, starting a service and enabling it are not the same thing. Understanding that distinction prevents many common mistakes.

What Is systemd?

systemd is a collection of core Linux components. Its system and service manager normally runs as process ID 1 and starts the rest of the operating system.

It manages much more than conventional background services, including:

  • Devices
  • Mount points
  • Swap
  • Sockets
  • Timers
  • User sessions
  • System targets
  • Logging through the journal
  • Dependencies between system components

systemd tracks processes using Linux control groups and can start services in response to boot targets, sockets, devices, timers and other events. 

The main command used to interact with it is:

systemctl

What Is a Unit?

systemd manages objects called units.

Common unit types include:

.service

.socket

.target

.timer

.mount

.automount

.path

.device

.swap

For ordinary service management, you will usually work with .service units.

Examples include:

ssh.service

nginx.service

apache2.service

docker.service

cups.service

NetworkManager.service

When the unit type is unambiguous, systemctl normally lets you omit .service.

These commands are therefore generally equivalent:

sudo systemctl restart ssh

sudo systemctl restart ssh.service

Using the complete unit name can be clearer in scripts and documentation.

Distribution Names Can Differ

The service name is not always the same on every Linux distribution.

For example, the OpenSSH server might be called:

ssh.service

on Debian or Ubuntu, but:

sshd.service

on Fedora or other distributions.

Similarly, the Apache web server is commonly:

apache2.service

on Debian-based systems and:

httpd.service

on Fedora or Red Hat-based systems.

Always confirm the unit name rather than guessing.

Check Whether a Service Exists

To inspect a known service:

systemctl status service-name

For example:

systemctl status ssh

You may see output similar to:

● ssh.service - OpenBSD Secure Shell server

     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled)

     Active: active (running)

   Main PID: 1248 (sshd)

      Tasks: 1

     Memory: 4.2M

        CPU: 87ms

The most important lines are:

  • Loaded — whether systemd found the unit file
  • Enabled or disabled — whether it is configured for automatic activation
  • Active — its current runtime state
  • Main PID — the main process associated with it
  • Recent journal entries — messages explaining its latest activity

systemctl status is intended to provide human-readable runtime information and recent log output for the selected unit. systemd’s related administration tools expose service state, dependencies and journal information through the same management framework. 

Starting a Service

To start a service immediately:

sudo systemctl start service-name

For example:

sudo systemctl start nginx

This requests that systemd activate the unit now.

It does not necessarily configure the service to start after the next reboot.

Check that it started:

systemctl status nginx

Or use a simpler machine-friendly check:

systemctl is-active nginx

Possible results include:

active

inactive

failed

activating

deactivating

Stopping a Service

To stop a running service:

sudo systemctl stop service-name

For example:

sudo systemctl stop nginx

Then confirm:

systemctl is-active nginx

Stopping a service affects its current runtime state. It does not normally prevent it from starting again after reboot or being activated by another unit.

A stopped service can also be started again automatically if it is:

  • Socket-activated
  • Triggered by a timer
  • Required by another unit
  • Started by an administrator
  • Restarted by its own configured recovery policy

If a service immediately returns after being stopped, inspect its dependencies, sockets, timers and restart settings rather than repeatedly stopping it.

Restarting a Service

To stop and then start a service:

sudo systemctl restart service-name

For example:

sudo systemctl restart ssh

Restarting is commonly required after changing configuration files.

Be careful when restarting:

  • SSH on a remote server
  • Networking
  • Firewalls
  • Storage services
  • Databases
  • Virtualisation platforms
  • Authentication services

A bad configuration could disconnect your remote session or interrupt users.

Where the application provides a configuration-test command, run that first.

For Nginx:

sudo nginx -t

For Apache on many systems:

sudo apachectl configtest

For OpenSSH:

sudo sshd -t

Only restart after the configuration test succeeds.

Reloading a Service

Some services can reload their configuration without fully stopping.

Use:

sudo systemctl reload service-name

For example:

sudo systemctl reload nginx

Reloading can reduce interruption because the running service remains available while rereading its configuration.

Not every unit supports reload.

Check using:

systemctl show service-name -p CanReload

A result of:

CanReload=yes

means the unit declares reload support.

If reload is unsupported, systemctl will normally report an error rather than silently restarting the service.

Reload or Restart Automatically

You can ask systemd to reload when supported and restart otherwise:

sudo systemctl reload-or-restart service-name

This is useful in maintenance scripts when the service’s capabilities may vary.

However, it can conceal whether the operation interrupted the service, so use it thoughtfully on critical systems.

Start Versus Enable

This is the most important systemd distinction.

Start

sudo systemctl start nginx

Starts the service now.

Enable

sudo systemctl enable nginx

Configures the service for automatic activation through the dependencies defined in its unit file, commonly during boot.

Enabling does not normally start the service immediately.

To both enable and start it:

sudo systemctl enable --now nginx

This combines two actions:

  1. Enable the unit for future automatic activation.
  2. Start it in the current session.

Check Whether a Service Is Enabled

Run:

systemctl is-enabled service-name

For example:

systemctl is-enabled nginx

Possible results include:

enabled

disabled

static

masked

indirect

generated

enabled

The unit has the appropriate links or configuration for automatic activation.

disabled

The unit is available but not enabled through its install configuration.

It can still be started manually or as a dependency.

static

The unit does not normally contain installation instructions for direct enabling.

It may instead be started because another unit depends on it.

masked

The unit has been deliberately blocked from starting.

generated

The unit was created dynamically, often from another configuration source.

Do not assume that anything other than enabled means broken.

Disabling a Service

To remove its normal automatic-start configuration:

sudo systemctl disable service-name

For example:

sudo systemctl disable nginx

This does not normally stop the currently running service.

To disable and stop it together:

sudo systemctl disable --now nginx

A disabled service can still be:

  • Started manually
  • Started by another unit
  • Activated through a socket
  • Triggered by a timer
  • Started through D-Bus or device activation

Disabling is therefore different from completely blocking activation.

Masking a Service

To prevent a service from being started at all:

sudo systemctl mask service-name

For example:

sudo systemctl mask cups

A masked unit normally points to /dev/null, causing activation attempts to fail.

To mask and stop it:

sudo systemctl mask --now cups

To allow it again:

sudo systemctl unmask cups

Masking is stronger than disabling.

Use it when a service must not be activated accidentally, but be careful with core system units. Masking networking, login, storage or security components can prevent normal startup or remote access.

Why a Disabled Service May Still Start

A disabled service can still start because “disabled” only means it has not been installed into its normal boot target through systemctl enable.

Another unit may contain a dependency such as:

Requires=example.service

or:

Wants=example.service

A socket or timer may also activate it.

Check what caused the activation with:

systemctl status service-name

Then inspect dependencies:

systemctl list-dependencies service-name

For reverse dependencies:

systemctl list-dependencies --reverse service-name

You can also look for related units:

systemctl list-unit-files | grep example

Possible related units might include:

example.service

example.socket

example.timer

example.path

systemd supports dependency-driven and on-demand activation, including socket and device activation, so a service does not need to be directly enabled to run. 

Check All Running Services

List active service units:

systemctl list-units --type=service

Show only running services:

systemctl list-units --type=service --state=running

Show failed services:

systemctl --failed

Or specifically:

systemctl list-units --type=service --state=failed

The failed list is a useful first check after:

  • A problematic boot
  • A package upgrade
  • A power failure
  • A configuration change
  • A server outage

List Installed Service Unit Files

To list service definitions whether active or not:

systemctl list-unit-files --type=service

This displays states such as:

enabled

disabled

static

masked

This differs from:

systemctl list-units

list-units shows units currently loaded into systemd’s runtime state, while list-unit-files focuses on unit files installed on disk.

View Service Logs

The systemd journal stores structured log messages collected by systemd-journald.

To view logs for one service:

journalctl -u service-name

For example:

journalctl -u nginx

journalctl reads entries from the systemd journal and can filter them by fields such as the associated systemd unit. 

Show Recent Logs

To show the latest entries:

journalctl -u nginx -n 50

This displays the most recent 50 lines.

For logs from the current boot:

journalctl -u nginx -b

For the previous boot:

journalctl -u nginx -b -1

To show errors since today:

journalctl -u nginx --since today

For a specific period:

journalctl -u nginx \

    --since "2026-08-01 08:00" \

    --until "2026-08-01 09:00"

Follow Logs Live

To watch new messages as they arrive:

journalctl -u nginx -f

This is similar to following a traditional log file with:

tail -f

Press:

Ctrl + C

to stop following.

This is especially useful while reproducing a fault in another terminal.

Show More Detailed Errors

For explanations and related metadata:

journalctl -xeu service-name

For example:

journalctl -xeu ssh

The options mean broadly:

  • -x — add explanatory text where available
  • -e — jump near the end
  • -u — filter for the selected unit

Do not focus only on the final line. The real cause may appear several messages earlier.

A Service Is “Failed”

Check its status:

systemctl status service-name

Then inspect its logs:

journalctl -xeu service-name

Common causes include:

  • Invalid configuration syntax
  • Missing files
  • Wrong permissions
  • An occupied network port
  • A failed dependency
  • Incorrect credentials
  • Missing environment variables
  • A damaged package
  • A storage volume not being mounted
  • A security policy blocking access
  • The process exiting immediately

After fixing the cause, reset the failed state if necessary:

sudo systemctl reset-failed service-name

Then start it:

sudo systemctl start service-name

reset-failed clears the remembered failed state and also resets certain start-rate counters. It does not repair the service itself.

“Start Request Repeated Too Quickly”

systemd can limit how often it tries to restart a repeatedly failing unit.

You may see:

Start request repeated too quickly

This usually means:

  1. The service started.
  2. It failed quickly.
  3. systemd retried it.
  4. It failed repeatedly.
  5. systemd stopped retrying to avoid an endless loop.

Do not merely reset the failure and repeatedly start it.

First inspect:

systemctl status service-name

journalctl -u service-name -b

Fix the underlying application or configuration problem, then run:

sudo systemctl reset-failed service-name

sudo systemctl start service-name

Viewing the Unit File

To display the unit file and any overrides:

systemctl cat service-name

For example:

systemctl cat ssh

This is safer than guessing the unit’s location.

It can show:

  • The main vendor file
  • Administrator overrides
  • Drop-in files
  • Runtime-generated settings

To see where the main file was loaded from:

systemctl show service-name -p FragmentPath

Common Unit-File Locations

System unit files may be found under locations such as:

/etc/systemd/system

/run/systemd/system

/usr/lib/systemd/system

/lib/systemd/system

The exact vendor path differs between distributions.

As a general rule:

  • Distribution packages place their unit files under a vendor directory such as /usr/lib/systemd/system
  • Administrator-created units and overrides belong under /etc/systemd/system
  • /run/systemd/system contains temporary runtime configuration

Do not directly edit a package-supplied unit under /usr/lib or /lib. A package upgrade may overwrite the change.

Editing a Service Safely

To create an override:

sudo systemctl edit service-name

This opens an editor for a drop-in file, normally under a path similar to:

/etc/systemd/system/service-name.service.d/override.conf

For example:

sudo systemctl edit nginx

You might add:

[Service]

Restart=on-failure

RestartSec=5s

Save and exit, then reload systemd’s unit configuration:

sudo systemctl daemon-reload

Restart the service if the new setting must apply immediately:

sudo systemctl restart nginx

What Does

daemon-reload

Do?

Run:

sudo systemctl daemon-reload

after:

  • Creating a unit file
  • Editing a unit file
  • Adding or changing a drop-in
  • Changing dependency links manually
  • Modifying certain generator inputs

daemon-reload tells the system manager to rerun generators, reread unit files and rebuild its dependency information.

It does not restart all services.

It also does not necessarily apply new service settings to a process that is already running. Restart or reload the affected service afterwards where required.

Official systemd debugging guidance specifically calls for daemon-reload when configuration changes require the manager to refresh its view of units and generated dependencies. 

Do Not Confuse These Three Commands

Reload the service

sudo systemctl reload nginx

Asks the application to reread its own configuration.

Restart the service

sudo systemctl restart nginx

Stops and starts the application process.

Reload systemd’s unit definitions

sudo systemctl daemon-reload

Makes systemd reread unit files.

They solve different problems.

Reverting Local Overrides

To remove overrides and return to the package-supplied unit:

sudo systemctl revert service-name

Review what will be removed before confirming.

Then run:

sudo systemctl daemon-reload

sudo systemctl restart service-name

where appropriate.

You can also inspect the existing override before removing it:

systemctl cat service-name

Creating a Basic Custom Service

Suppose you have a script:

/usr/local/bin/example-worker

Create a unit:

sudo nano /etc/systemd/system/example-worker.service

Add:

[Unit]

Description=Example Background Worker

After=network.target


 

[Service]

Type=simple

ExecStart=/usr/local/bin/example-worker

Restart=on-failure

RestartSec=5s


 

[Install]

WantedBy=multi-user.target

Then:

sudo systemctl daemon-reload

sudo systemctl enable --now example-worker.service

Check it:

systemctl status example-worker.service

View logs:

journalctl -u example-worker.service

Understanding the Unit Sections

[Unit]

Contains general metadata and dependencies.

[Unit]

Description=Example Background Worker

After=network.target

[Service]

Describes how the service starts and behaves.

[Service]

Type=simple

ExecStart=/usr/local/bin/example-worker

Restart=on-failure

[Install]

Describes what should happen when the unit is enabled.

[Install]

WantedBy=multi-user.target

Without an appropriate [Install] section, systemctl enable may report that the unit has no installation configuration.

That does not necessarily mean the unit is invalid. It may be intended to start only as a dependency or through another form of activation.

Use Absolute Paths

For system services, use full executable paths:

ExecStart=/usr/local/bin/example-worker

Do not rely on shell aliases or an interactive user’s PATH.

This is unreliable:

ExecStart=example-worker

Find the executable path with:

command -v example-worker

Also remember that ExecStart= does not automatically run through an interactive shell.

Shell features such as these will not behave as expected unless you deliberately invoke a shell:

|

>

>>

&&

$VARIABLE

*

Prefer a proper script with an explicit interpreter rather than placing a complicated shell command directly in the unit.

Set the Correct User

System services run as root by default unless configured otherwise.

To run the process as a dedicated account:

[Service]

User=example

Group=example

ExecStart=/usr/local/bin/example-worker

Running an internet-facing or file-processing service as root unnecessarily increases the impact of a compromise or programming error.

Give the service only the permissions it requires.

Set the Working Directory

If the program expects to start in a particular folder:

[Service]

WorkingDirectory=/srv/example

ExecStart=/usr/local/bin/example-worker

Do not assume it will start in the same directory as the unit file or script.

Environment Variables

You can define individual variables:

[Service]

Environment="APP_MODE=production"

Environment="PORT=8080"

Or load them from a file:

[Service]

EnvironmentFile=/etc/example-worker.conf

Protect files containing passwords, API keys or database credentials:

sudo chown root:root /etc/example-worker.conf

sudo chmod 600 /etc/example-worker.conf

Avoid including secrets directly in broadly readable unit files where better credential-management methods are available.

Service Types

The Type= setting tells systemd how to determine that startup has succeeded.

Common values include:

simple

The process started by ExecStart= is treated as the main service process.

Type=simple

This is suitable for many programs that remain in the foreground.

exec

Similar to simple, but systemd considers startup successful only after the service executable has been invoked successfully.

forking

Used by traditional daemons that start and then fork into the background.

Type=forking

Modern applications should generally run in the foreground under systemd rather than daemonising themselves where supported.

oneshot

Used for a command that runs once and exits.

Type=oneshot

RemainAfterExit=yes

notify

The service explicitly tells systemd when it has completed startup.

Choose the type documented by the application rather than guessing.

Restart Policies

Common policies include:

Restart=no

Restart=on-failure

Restart=always

no

Do not automatically restart.

on-failure

Restart after abnormal exits, signals or timeouts, depending on the detailed settings.

always

Restart regardless of why the process exited.

For most ordinary long-running services:

Restart=on-failure

is safer than always.

Do not use automatic restarts to hide a repeating crash. Monitor the logs and fix the actual fault.

Dependencies and Ordering Are Different

A frequent mistake is assuming that:

After=network.target

causes network.target to start.

It does not.

After= controls ordering when both units are part of the same transaction.

Dependencies are expressed separately with directives such as:

Wants=

Requires=

For example:

[Unit]

Wants=network-online.target

After=network-online.target

Even then, “network online” depends on the relevant wait-online service and network configuration. Being ordered after network.target does not by itself mean a usable network connection is available. The official systemd documentation explicitly warns about this distinction in network-dependent service configurations. 

Wants=

Versus

Requires=

Wants=

Creates a weaker dependency.

systemd attempts to start the listed unit, but your service may still start when that other unit fails.

Requires=

Creates a stronger requirement.

When the required unit fails to activate, the requesting unit is generally not started. Depending on ordering and runtime relationships, stopping or failure behaviour can still require additional directives.

Do not use Requires= everywhere. It can create unnecessary coupling and make the system less resilient.

Targets

Targets group units and represent system states or synchronisation points.

Common targets include:

multi-user.target

graphical.target

network.target

network-online.target

rescue.target

emergency.target

A server service often includes:

[Install]

WantedBy=multi-user.target

A graphical desktop component may instead be associated with:

graphical.target

To see the current default target:

systemctl get-default

Typical output:

graphical.target

or:

multi-user.target

User Services

systemd can also manage services for an individual user.

Use:

systemctl --user status service-name

Start one:

systemctl --user start service-name

Enable one:

systemctl --user enable service-name

Enable and start:

systemctl --user enable --now service-name

User service files may be stored under:

~/.config/systemd/user

After changing one:

systemctl --user daemon-reload

Logs can be viewed with:

journalctl --user -u service-name

A user systemd manager is distinct from the system manager and can persist across multiple sessions according to the system’s login-manager configuration. 

User Services After Logout

A normal user service may stop when the user has no remaining sessions.

To allow the user manager to remain active after logout:

sudo loginctl enable-linger username

Disable it with:

sudo loginctl disable-linger username

Use lingering only where there is a genuine requirement for the user’s services to run without an interactive login.

For system-wide infrastructure, a proper system service may be more appropriate.

Find Which Process Uses a Port

A service may fail because another process already occupies its port.

For example:

sudo ss -ltnp

To check port 80:

sudo ss -ltnp 'sport = :80'

You may find that:

  • Apache is already using the port intended for Nginx
  • A manually started process conflicts with the service
  • An old development server is still running
  • A container has published the same port

Do not kill the process until you identify why it is there.

Check Unit Dependencies

Display the dependency tree:

systemctl list-dependencies service-name

Reverse the direction:

systemctl list-dependencies --reverse service-name

Inspect specific unit properties:

systemctl show service-name

Useful individual properties include:

systemctl show service-name -p ActiveState

systemctl show service-name -p SubState

systemctl show service-name -p MainPID

systemctl show service-name -p Restart

systemctl show service-name -p FragmentPath

systemctl show is more suitable for scripts than parsing the decorative output of systemctl status.

Check for Stuck Jobs

List systemd jobs currently being processed:

systemctl list-jobs

This can help when boot, shutdown or service activation appears to be waiting indefinitely.

Official systemd debugging guidance recommends checking service status, logs and pending jobs when investigating startup problems. 

Validate Unit Files

Run:

systemd-analyze verify /etc/systemd/system/example-worker.service

This can detect:

  • Unknown directives
  • Missing dependencies
  • Invalid executable paths
  • Syntax problems
  • Certain ordering issues

A clean result does not prove that the application itself will work, but it can catch unit-file mistakes before deployment.

Do Not Edit Units with Windows Line Endings

A unit or script created in a Windows editor may contain CRLF line endings.

This can lead to confusing execution errors, especially for scripts with a shebang such as:

#!/bin/bash

Check with:

file /usr/local/bin/example-worker

Convert where appropriate using a trusted editor or:

dos2unix /usr/local/bin/example-worker

Also make sure the script is executable:

sudo chmod 755 /usr/local/bin/example-worker

Permission Problems

If the service reports:

Permission denied

check:

  • The executable bit
  • Parent-directory access
  • The configured User= and Group=
  • File ownership
  • SELinux or AppArmor
  • Mount options such as noexec
  • Access to sockets and devices
  • Whether a protected directory is writable

Do not respond by making every file world-writable.

This is rarely appropriate:

chmod -R 777 /path

Give the service account the narrowest access it needs.

SELinux and AppArmor

A service can have apparently correct Unix permissions and still be blocked by a mandatory access-control system.

On SELinux systems, inspect recent denials using the distribution’s supported tools and logs.

On AppArmor systems, check whether the service’s profile is denying a path or capability.

Do not disable SELinux or AppArmor globally simply to make one service run.

Correct the path, package, label or policy instead.

Services Installed from Containers or Sandboxed Packages

Not every application is managed by a conventional host .service unit.

It may instead be controlled by:

  • Docker
  • Podman
  • Kubernetes
  • Snap
  • Flatpak
  • A user service
  • A process supervisor inside a container

For example, restarting:

sudo systemctl restart docker

restarts the Docker daemon and may affect many containers. It is not the same as restarting one container.

Use the correct management layer for the application.

Do Not Repeatedly Use

kill -9

systemd normally stops a service using its configured shutdown behaviour and signals.

A forced:

kill -9 PID

does not allow the process to:

  • Flush data
  • Close connections
  • Remove temporary files
  • Commit database transactions
  • Release locks cleanly

Use:

sudo systemctl stop service-name

first.

Reserve forced termination for a genuinely stuck process after understanding the data risk.

A Safe Service-Management Workflow

When working with a systemd service:

  1. Confirm the exact unit name.
  2. Check its current status.
  3. Review recent journal entries.
  4. Test the application’s configuration.
  5. Start, stop, reload or restart it as required.
  6. Confirm the resulting state.
  7. Enable it only if it should activate automatically.
  8. Use --now when you also want the immediate runtime action.
  9. Use an override instead of editing a vendor unit.
  10. Run daemon-reload after unit-file changes.
  11. Restart the service if the new runtime settings require it.
  12. Check logs after every significant change.
  13. Mask only when activation must be completely blocked.
  14. Keep another administrative session open when changing remote-access or networking services.

Quick systemctl Reference

Status

systemctl status example.service

Start now

sudo systemctl start example.service

Stop now

sudo systemctl stop example.service

Restart

sudo systemctl restart example.service

Reload configuration

sudo systemctl reload example.service

Enable at boot

sudo systemctl enable example.service

Enable and start now

sudo systemctl enable --now example.service

Disable automatic activation

sudo systemctl disable example.service

Disable and stop now

sudo systemctl disable --now example.service

Block all activation

sudo systemctl mask example.service

Remove the block

sudo systemctl unmask example.service

Read logs

journalctl -u example.service

Follow logs live

journalctl -u example.service -f

Reload unit definitions

sudo systemctl daemon-reload

List failed units

systemctl --failed

Need Help Managing Linux Services?

A single systemd command can restore a failed service, but incorrect dependency, permission or restart settings can cause repeated crashes, boot delays or unexpected outages.

Hamilton Group can diagnose failing Linux services, review unit files and logs, configure secure automatic startup and help maintain reliable Linux workstations and servers.

Call 0330 043 0069 or visit hgmssp.com to speak with one of our IT experts.