A stylized terminal window on a laptop.
Fatmawati Achmad Zaenuri/Shutterstock

Need to launch a Linux program at boot? The systemd software provides a way to do it on any Linux distro with systemd—which is most of them these days, including Ubuntu. We’ll walk you through the process of creating an integrated service—and it even talks to the journal.

This tutorial demonstrates how to set up a system service that launches when you start your system. To launch a graphical program when you sign in, use your desktop’s startup manager instead.

Running Programs at Startup

Sometimes the software you install on your computer hooks itself into the Linux startup process, so that the program is automatically launched each time the computer is started. You can easily achieve this same behavior with your own programs and scripts, or in fact any other program that is on your computer.

The programs that are launched at startup are controlled by systemd, the system and service manager. systemd is the first process to run at startup. It always has process ID (PID) 1. Every other process running in your computer is started by systemd, or by a process that systemd has already started.

Programs that run in the background are called daemons or services. The “d” at the end of systemd stands for daemon. In this article, we’ll create an example service. To tick all the boxes, our service must be:

  • Integrated with systemd through a service unit file
  • Launched at startup
  • Controllable using systemctl, the control interface for systemd
  • Able to write to the journal

Creating the Service Program

We need to have a program that systemd will launch. We’ll create a simple script, called “htg.sh”. This tutorial uses the Gedit text editor, but you can use whatever text editor you prefer.

touch htg.sh
gedit htg.sh

The gedit editor will open. Copy and paste the following text into the editor.


echo "htg.service: ## Starting ##" | systemd-cat -p info

while :
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "htg.service: timestamp ${TIMESTAMP}" | systemd-cat -p info
sleep 60

Save your changes and close the editor.

htg.sh script in the gedit editor

The script doesn’t do a whole lot, but there are a few points worth noting.

  • The two echo lines are piped through systemd-cat, a program that takes the output from a program and sends it to the journal. Entries to the journal are given a priority. We’re using the -p (priority) option to indicate that our messages are for information (info) only. They’re not important errors or warnings.
  • There is an endless while loop.
  • The TIMESTAMP variable is set to the current date and time. This is formatted into a message and sent to the journal.
  • The script then sleeps for 60 seconds.
  • After 60 seconds the loop is repeated. So, this script writes a timestamped message to the journal once per minute.

We’ll copy the script to the /usr/local/bin directory.

sudo cp htg.sh /usr/local/bin

And we need to make it executable:

sudo chmod +x /usr/local/bin/htg.sh

Creating the Service Unit File

Each program that is started by systemd has a definition file, called a service unit file. This holds certain attributes that systemd can use to locate and launch the program, and to define some of its behavior.

We need to create a unit file for our new service, but it is prudent to make sure none of the existing unit files have the name we want to give our new service.

sudo systemctl list-unit-files --type-service

You can scroll through the list of unit files, which is sorted alphabetically, and check that the name you want to use is not taken.

Our service is going to be called “htg.service”. No unit files have that name, so we can proceed and create our unit file.

sudo gedit /etc/systemd/system/htg.service

The gedit editor will open. Copy and paste the following text into the editor:

Description=How-To Geek Service Example

After=syslog.target network-online.target



Save your changes and close the editor.

htg.service unit file in the gedit editor

The entries have these meanings. These are typical entries. Our simple service doesn’t actually need most of them, but including them allows us to explain them.

  • Description: This is a text description of your service.
  • Wants: Our service wants—but doesn’t require—the network to be up before our service is started.
  • After: A list of unit names that should be started after this service has been successfully started, if they’re not already running.
  • Type: Simple. systemd will consider this service started as soon as the process specified by ExecStart has been forked.
  • ExecStart: The path to the process that should be started.
  • Restart: When and if the service should be restarted. We have set it to “on-failure.”
  • RestartSec: How long to wait before attempting to restart the service. This value is in seconds.
  • KillMode: Defines how systemd should kill the process if we ask systemctl to stop the service. We have this set to “process.” This causes systemd to use the SIGTERM signal on the main process only. If our service was a non-trivial program instead of a simple script, we would set this to “mixed” to ensure that any spawned processes were also terminated.
  • WantedBy: We have this set to “multi-user.target”, which means the service should be started as long as the system is in a state where multiple users can log in, whether or not a graphical user interface is available.

The unit file doesn’t need to be executable, but the permissions on the unit file should restrict who can edit it. You don’t want a malicious or mischievous user changing the unit file so that it executes a different program altogether.

This command will give the owner read and write permissions, and read permissions to the group. Others will have no permissions.

sudo chmod 640 /etc/systemd/system/htg.service

We can have systemctl check the syntax of our unit file for us, even if the service isn’t running yet. Any errors will be reported. (Actually, the “.service” part is optional for most commands.)

systemctl status htg.service

No errors are highlighted, which means our unit file is syntactically correct.

Starting the Service

When you add a new unit file or edit an existing one, you must tell systemd to reload the unit file definitions.

sudo systemctl daemon-reload

If you want a service to be launched at startup you must enable it:

sudo systemctl enable htg

Enabling a service doesn’t start it, it only sets it to be launched at boot time. To start the service now, you must use systemctl with the start option.

sudo systemctl start htg

Verifying the Service

After manually starting the service or after rebooting the computer, we can verify that our service is running correctly.

sudo systemctl status htg.service

The status of the service is displayed for us.

Status of htg.service in a terminal widnow

  • The green dot means our service is up and running smoothly.
  • The name of the service is “htg.service”, and the long description is the one that we provided in the unit file.
  • We’re shown which unit file has been loaded “/etc/systemd/system/htg.service”.
  • The service is active, and the time the service was launched is listed for us.
  • Its PID is 7762.
  • There are two tasks associated with the service.
  • A total of 928 Kibibytes of memory are being used by the service.
  • The control group includes the “htg.sh” script and the sleep command, which has been launched by “htg.sh.” Most of the time, the sleep command will be doing the work for this service.

We’re also shown the last 10 journal entries produced by this service. Unsurprisingly, they are all one minute apart.

Stopping and Disabling the Service

If you need to stop the service, you can do so with this command:

sudo systemctl stop htg.service

This stops the service, but it doesn’t prevent it from restarting next time the computer is rebooted. To stop the service being launched at startup, you need to disable it:

sudo systemctl disable htg.service

If the service is running, this command doesn’t stop it. It simply tells systemd not to launch the service at the next reboot.

If you want to stop the service and prevent it from launching at startup, use both commands.

Service Tip

Make sure your program runs as expected before you try to launch it as a service.

Dave McKay Dave McKay
Dave McKay first used computers when punched paper tape was in vogue, and he has been programming ever since. After over 30 years in the IT industry, he is now a full-time technology journalist. During his career, he has worked as a freelance programmer, manager of an international software development team, an IT services project manager, and, most recently, as a Data Protection Officer. Dave is a Linux evangelist and open source advocate.
Read Full Bio »

The above article may contain affiliate links, which help support How-To Geek.