Introduction
In this lab, you will gain hands-on experience managing system services on RHEL using the systemctl command. You will learn to view all loaded and active services, check the status of specific services, and control their runtime behavior by starting, stopping, and restarting them. Furthermore, you will explore how to reload service configurations, enable or disable services for automatic startup at boot, and understand the advanced concepts of masking and unmasking services to prevent their activation.
This practical guide will equip you with essential skills for system administration, enabling you to effectively monitor and manage the lifecycle of services crucial for the operation of your RHEL system.
View All Loaded and Active Services with systemctl
In this step, you will learn how to identify automatically started system processes using the systemctl command. systemctl is the primary tool for managing systemd services in Red Hat Enterprise Linux.
First, let's explore how to list all currently loaded and active service units. The systemctl list-units --type=service command is used for this purpose. This command displays service units that the systemd daemon has successfully parsed and loaded into memory, and which are currently active.
Open your terminal in the RHEL environment. You are already logged in as the labex user, and your current directory is ~/project.
Execute the following command to list all loaded and active service units:
systemctl list-units --type=service
You will see output similar to this, showing various services and their states:
UNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running Job spooling tools
auditd.service loaded active running Security Auditing Service
chronyd.service loaded active running NTP client/server
crond.service loaded active running Command Scheduler
dbus-broker.service loaded active running D-Bus System Message Bus
...output omitted...
Let's break down the columns in the output:
- UNIT: This is the name of the service unit, typically ending with
.service. - LOAD: Indicates whether the
systemddaemon successfully parsed the unit's configuration and loaded it into memory.loadedmeans it was successful. - ACTIVE: This is the high-level activation state of the unit.
activegenerally means the unit started successfully. - SUB: This is the low-level activation state, providing more detailed information. For running services,
runningis common. - DESCRIPTION: A brief description of what the service does.
Press q to exit the command.
Next, you can use the --all option with systemctl list-units --type=service to list all service units regardless of their activation states (active, inactive, failed, etc.). This can be useful for seeing services that are installed but not currently running.
Execute the following command:
systemctl list-units --type=service --all
The output will include services that are inactive or in other states, providing a more comprehensive view:
UNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running Job spooling tools
auditd.service loaded active running Security Auditing ...
auth-rpcgss-module.service loaded inactive dead Kernel Module ...
chronyd.service loaded active running NTP client/server
cpupower.service loaded inactive dead Configure CPU power ...
crond.service loaded active running Command Scheduler
dbus-broker.service loaded active running D-Bus System Message Bus
● display-manager.service not-found inactive dead display-manager.service
...output omitted...
Finally, to see the state of all installed unit files, including those that are not loaded or active, you can use systemctl list-unit-files --type=service. This command shows whether a service is enabled (starts at boot), disabled (does not start at boot), static (cannot be enabled directly but might be started by another unit), or masked (prevented from starting).
Execute the following command:
systemctl list-unit-files --type=service
You will see output similar to this, indicating the STATE and VENDOR PRESET for each service unit file:
UNIT FILE STATE VENDOR PRESET
arp-ethers.service disabled disabled
atd.service enabled enabled
auditd.service enabled enabled
auth-rpcgss-module.service static -
autovt@.service alias -
blk-availability.service disabled disabled
...output omitted...
This command is particularly useful for understanding which services are configured to start automatically when the system boots up.
Check Status of a Specific Service with systemctl status
In this step, you will learn how to check the detailed status of a specific service using the systemctl status command. This command provides comprehensive information about a service, including whether it's running, its process ID, memory usage, and recent log entries.
We will use the crond.service (cron daemon) as an example. The cron daemon is a common service that handles scheduled tasks.
Open your terminal in the RHEL environment. Ensure you are in your ~/project directory.
Execute the following command to check the status of the crond.service:
systemctl status crond.service
You will see detailed output similar to this:
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; preset: enabled)
Active: active (running) since Mon 2022-03-14 05:38:10 EDT; 25min ago
Main PID: 1089 (crond)
Tasks: 1 (limit: 35578)
Memory: 1.2M
CPU: 12ms
CGroup: /system.slice/crond.service
└─1089 /usr/sbin/crond -n
Mar 14 05:38:10 workstation systemd[1]: Started Command Scheduler.
Warning: some journal files were not opened due to insufficient permissions.
Let's examine the key fields in the output:
Loaded: This line tells you if the service unit's configuration file has been processed. It also shows the path to the unit file (/usr/lib/systemd/system/crond.service) and its enablement status (enabledmeans it's configured to start at boot).Active: This is crucial. It indicates the current state of the service.active (running)means the service is currently active and its processes are running. It also shows how long it has been active. Other states could beinactive(not running),active (exited)(completed a one-time task), orfailed(encountered an error).Main PID: The Process ID (PID) of the main process associated with the service, along with the command name.Tasks: The number of tasks (threads) the service is currently using.Memory: The amount of memory the service is consuming.CPU: The CPU time consumed by the service.CGroup: Information about the control group the service belongs to, which is used for resource management.- The lines below
CGroupshow recent log entries related to the service, providing insights into its startup and ongoing activities.
In addition to systemctl status, there are simpler commands to quickly check specific aspects of a service's state:
To check if a service is active:
systemctl is-active crond.serviceExpected output:
activeTo check if a service is enabled (configured to start at boot):
systemctl is-enabled crond.serviceExpected output:
enabledTo check if a service has failed:
systemctl is-failed crond.serviceExpected output (if running correctly):
activeIf a service had issues starting or running, this command would return
failed.
These commands are useful for scripting or quick checks when you don't need the full detailed output of systemctl status.
Start, Stop, and Restart a Service with systemctl
In this step, you will learn how to manage the lifecycle of system services using systemctl commands. You will practice starting, stopping, and restarting a service. For this exercise, we will use a dummy service that we will create. This approach ensures that we can safely manipulate a service without affecting critical system functions.
First, let's create a simple service unit file. This file will define a service that simply writes a timestamp to a log file every few seconds.
Create a new service unit file named mytest.service directly in the systemd system directory using nano:
sudo nano /etc/systemd/system/mytest.service
Paste the following content into the nano editor:
[Unit]
Description=My Test Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "$(date): My Test Service is running." >> /tmp/mytest.log; sleep 5; done'
ExecStop=/bin/bash -c 'echo "$(date): My Test Service stopped." >> /tmp/mytest.log'
Restart=on-failure
[Install]
WantedBy=multi-user.target
[Unit]: Contains generic information about the unit.Descriptionprovides a human-readable name, andAfter=network.targetspecifies that this service should start after the network is up.[Service]: Defines the behavior of the service.Type=simple: Indicates a simple service type where theExecStartcommand is the main process.ExecStart: The command to execute when the service starts. Here, it's a bash loop that writes a timestamped message to/tmp/mytest.logevery 5 seconds.ExecStop: The command to execute when the service stops. It writes a stop message to the log.Restart=on-failure: Configures the service to restart if it exits with a non-zero status.
[Install]: Contains information about how the service should be installed.WantedBy=multi-user.targetmeans this service should be started when the system reaches the multi-user runlevel.
Save the file by pressing Ctrl+X, then Y to confirm, and Enter to save the file.
Now, reload the systemd daemon to recognize the new service file:
sudo systemctl daemon-reload
Starting a Service
To start a service, use the systemctl start command.
Execute the following command to start mytest.service. Note that we need to use sudo because systemctl operations typically require root privileges.
sudo systemctl start mytest.service
There will be no immediate output if the command is successful.
Now, verify that the service is running by checking its status:
systemctl status mytest.service
You should see output indicating that the service is active (running):
● mytest.service - My Test Service
Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
Active: active (running) since ...
Main PID: ... (bash)
Tasks: 2 (limit: ...)
Memory: ...
CPU: ...
CGroup: /system.slice/mytest.service
├─... /bin/bash -c "while true; do echo \"\$(date): My Test Service is running.\" >> /tmp/mytest.log; sleep 5; done"
└─... sleep 5
...output omitted...
You can also check the log file to see if the service is writing messages:
tail -f /tmp/mytest.log
You should see new lines appearing every 5 seconds, similar to this:
Tue Jul 22 09:15:09 AM CST 2025: My Test Service is running.
Tue Jul 22 09:15:14 AM CST 2025: My Test Service is running.
Press Ctrl+C to exit tail.
Stopping a Service
To stop a running service, use the systemctl stop command.
Execute the following command to stop mytest.service:
sudo systemctl stop mytest.service
Again, there will be no immediate output.
Verify that the service has stopped:
systemctl status mytest.service
The output should now show Active: inactive (dead):
○ mytest.service - My Test Service
Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
Active: inactive (dead) since ...
...output omitted...
Check the log file /tmp/mytest.log again. You should see the "My Test Service stopped." message and no new "running" messages appearing.
tail /tmp/mytest.log
The output will look similar to this:
Tue Jul 22 09:15:24 AM CST 2025: My Test Service is running.
Tue Jul 22 09:15:28 AM CST 2025: My Test Service stopped.
Restarting a Service
To restart a service, use the systemctl restart command. This command first stops the service and then starts it again. This is useful when you've made changes to a service's configuration and need them to take effect.
Execute the following command to restart mytest.service:
sudo systemctl restart mytest.service
Verify that the service is running again:
systemctl status mytest.service
You should see Active: active (running) again, and the Main PID will likely be a new number, indicating a new process has started.
● mytest.service - My Test Service
Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
Active: active (running) since ...
Main PID: ... (bash)
Tasks: 2 (limit: ...)
Memory: ...
CPU: ...
CGroup: /system.slice/mytest.service
├─... /bin/bash -c "while true; do echo \"\$(date): My Test Service is running.\" >> /tmp/mytest.log; sleep 5; done"
└─... sleep 5
...output omitted...
Check the log file /tmp/mytest.log to confirm that the service has resumed writing "running" messages.
tail -f /tmp/mytest.log
You should see a "stopped" message followed by new "running" messages:
Tue Jul 22 09:15:28 AM CST 2025: My Test Service stopped.
Tue Jul 22 09:15:40 AM CST 2025: My Test Service is running.
Press Ctrl+C to exit tail.
Applying Configuration Changes to a Service
In this step, you will learn about reloading service configurations. Some services can apply changes to their configuration files without needing a full restart. This is known as "reloading" the service. Reloading is generally preferred over restarting because it avoids service downtime and preserves existing connections or states. When a service is reloaded, its Process ID (PID) typically remains the same, unlike a full restart where the PID changes.
We will continue to use our mytest.service from the previous step. We will modify its behavior and then attempt to reload it to see what happens.
First, ensure mytest.service is running. If it's not, start it:
sudo systemctl start mytest.service
Verify its status and take note of its Main PID:
systemctl status mytest.service
Now, let's modify the mytest.service file to change the message it logs and the interval. We will change the log message and the sleep duration.
Open /etc/systemd/system/mytest.service with nano:
sudo nano /etc/systemd/system/mytest.service
Change the ExecStart line to the following, modifying the message and the sleep time from 5 to 2 seconds:
[Unit]
Description=My Test Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "$(date): My Test Service (reloaded) is running." >> /tmp/mytest.log; sleep 2; done'
ExecStop=/bin/bash -c 'echo "$(date): My Test Service stopped." >> /tmp/mytest.log'
Restart=on-failure
[Install]
WantedBy=multi-user.target
Save the file by pressing Ctrl+X, then Y, and Enter.
After saving the changes, you need to inform systemd that the service's configuration has changed.
sudo systemctl daemon-reload
Now, let's try to reload the service to apply the changes:
sudo systemctl reload mytest.service
You will likely encounter an error:
Failed to reload mytest.service: Job type reload is not applicable for unit mytest.service.
This error occurs because our simple service is not configured to handle a reload request. For a service to be reloadable, its unit file must include an ExecReload directive, which specifies the command to run to reload the configuration. Since our mytest.service lacks this, systemd doesn't know how to reload it.
In situations like this, systemd provides a convenient command: reload-or-restart. This command will attempt to reload the service, but if reloading is not supported, it will fall back to restarting the service. This is often a safer and more effective way to apply configuration changes.
Let's use reload-or-restart now:
sudo systemctl reload-or-restart mytest.service
This command should succeed. Now, check the status of the service again:
systemctl status mytest.service
Observe the Main PID. Since our service was restarted (because it couldn't be reloaded), you will notice that the Main PID is a new number. This confirms that the old process was stopped and a new one was started with the updated configuration.
Finally, let's check the /tmp/mytest.log file to see if the changes have taken effect.
tail -f /tmp/mytest.log
You should see the new log message "My Test Service (reloaded) is running." appearing every 2 seconds. Press Ctrl+C to exit tail.
Enable and Disable Services at Boot with systemctl
In this step, you will learn how to configure services to start automatically at boot time (enable) or prevent them from starting at boot (disable). This is crucial for managing system resources and ensuring that necessary services are available when the system starts.
In a typical systemd environment, enabling a service creates symbolic links in the appropriate systemd configuration directories (e.g., /etc/systemd/system/multi-user.target.wants/) that point to the service's unit file. Disabling a service removes these links.
Since we are in a containerized environment where systemd might not be fully operational in the traditional sense, the enable and disable commands might not create actual symlinks in the /etc/systemd/system directory that persist across container restarts. However, systemctl still processes these commands and updates its internal state, which is what we will observe.
We will continue to use our mytest.service for this demonstration.
First, ensure mytest.service is stopped from the previous step:
sudo systemctl stop mytest.service
Enabling a Service
To enable a service, use the systemctl enable command. This command configures the service to start automatically when the system boots.
Execute the following command to enable mytest.service:
sudo systemctl enable mytest.service
You might see output similar to this, indicating that a symbolic link would be created in a full systemd environment:
Created symlink /etc/systemd/system/multi-user.target.wants/mytest.service → /etc/systemd/system/mytest.service.
Now, verify that the service is enabled using systemctl is-enabled:
systemctl is-enabled mytest.service
Expected output:
enabled
This confirms that systemctl now considers mytest.service to be enabled for boot.
You can also combine enabling and starting a service in one command using the --now option. This is a convenient way to ensure a service is both running immediately and configured to start on future boots.
First, let's disable it to prepare for the --now demonstration:
sudo systemctl disable mytest.service
Now, enable and start it simultaneously:
sudo systemctl enable --now mytest.service
Verify its status and enablement:
systemctl status mytest.service
systemctl is-enabled mytest.service
You should see Active: active (running) from the status command and enabled from the is-enabled command.
Disabling a Service
To disable a service, use the systemctl disable command. This command removes the configuration that causes the service to start at boot time.
Execute the following command to disable mytest.service:
sudo systemctl disable mytest.service
You might see output indicating the removal of the symbolic link:
Removed /etc/systemd/system/multi-user.target.wants/mytest.service.
Now, verify that the service is disabled:
systemctl is-enabled mytest.service
Expected output:
disabled
Similar to enabling, you can combine disabling and stopping a service using the --now option. This will stop the service immediately and prevent it from starting on future boots.
sudo systemctl disable --now mytest.service
Verify its status and enablement:
systemctl status mytest.service
systemctl is-enabled mytest.service
You should see Active: inactive (dead) from the status command and disabled from the is-enabled command.
This concludes the demonstration of enabling and disabling services. Remember that in a real systemd environment, these commands directly manipulate the boot configuration.
Mask and Unmask Services with systemctl
In this final step, you will learn about masking and unmasking services. Masking a service is a powerful way to prevent it from being started, either manually or automatically at boot.
When you mask a service, systemd creates a symbolic link from /etc/systemd/system/<service-name>.service to /dev/null, effectively making the service unit file unavailable to systemd. This is a stronger alternative to disable.
This mechanism works best for services that are defined in /usr/lib/systemd/system, which is where packages install their service files. The mask command creates an overriding "empty" file in /etc/systemd/system. However, as you have discovered, if you try to mask a service that you created directly in /etc/systemd/system (like our mytest.service), the command can fail because it is designed to not overwrite an existing configuration file, which would cause data loss.
To demonstrate masking correctly, we will use a pre-existing service, atd.service.
First, let's check the current status of atd.service. It should be active and enabled.
systemctl status atd.service
The output will be similar to this, showing the service is active and running:
● atd.service - Deferred execution scheduler
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; preset: enabled)
Active: active (running) since Tue 2025-07-22 09:13:06 CST; 22min ago
Docs: man:atd(8)
Main PID: 1222 (atd)
Tasks: 1 (limit: 22509)
Memory: 900.0K
CPU: 5ms
CGroup: /system.slice/atd.service
└─1222 /usr/sbin/atd -f
Masking a Service
It's good practice to stop a service before masking it.
sudo systemctl stop atd.service
Now, execute the following command to mask atd.service:
sudo systemctl mask atd.service
You will see output indicating the creation of a symbolic link to /dev/null:
Created symlink /etc/systemd/system/atd.service → /dev/null.
Now, try to start the masked service:
sudo systemctl start atd.service
You will receive an error message, indicating that the service is masked:
Failed to start atd.service: Unit atd.service is masked.
You can also check the state of the service using systemctl list-unit-files:
systemctl list-unit-files --type=service | grep atd.service
The output should show masked for atd.service:
atd.service masked enabled
This confirms that the service is now masked and cannot be started.
Unmasking a Service
To unmask a service, use the systemctl unmask command. This command removes the symbolic link to /dev/null, restoring the original service file from /usr/lib/systemd/system.
Execute the following command to unmask atd.service:
sudo systemctl unmask atd.service
You will see output indicating the removal of the symbolic link:
Removed "/etc/systemd/system/atd.service".
Now, check the state of the service using systemctl list-unit-files again:
systemctl status atd.service
You should see Active: active (running), similar to this:
● atd.service - Deferred execution scheduler
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; preset: enabled)
Active: active (running) since Tue 2025-07-22 09:36:10 CST; 2s ago
Docs: man:atd(8)
Main PID: 7372 (atd)
Tasks: 1 (limit: 22509)
Memory: 868.0K
CPU: 6ms
CGroup: /system.slice/atd.service
└─7372 /usr/sbin/atd -f
This concludes the lab on controlling services and daemons. You have learned how to view, start, stop, restart, reload, enable, disable, mask, and unmask services using systemctl.
Summary
In this lab, we gained hands-on experience managing control system services using the systemctl command, even within a containerized environment where systemd might not be the primary init system. We learned how to list all loaded and active service units using systemctl list-units --type=service, understanding the UNIT, LOAD, ACTIVE, and SUB columns to interpret service states.
Furthermore, we explored essential service management operations: checking the status of a specific service with systemctl status, and controlling service lifecycle by starting, stopping, and restarting services. We also covered how to reload service configurations, enable and disable services to control their behavior at boot time, and the advanced concepts of masking and unmasking services to prevent them from being started. This comprehensive set of skills provides a solid foundation for managing services on RHEL systems.



