In this lesson,
we'll show how to create a systemd service file and the best way
to understand why we need such a service and how to define it
is to go through a practical exercise.
Let's assume we built some sort of application one that
needs to run on our servers all the time.
Now, the issue with programs is they can occasionally crash.
So we want something to keep a watchful eye on
our application and restart it if it ever fails.
Also, we might want it to automatically start up when the system boots,
systemd services can do both of these things and more.
Let's add these lines.
Now, the first echo line sends a message to the system log stating that my app started
system D dash C
is the utility that receives the message and logs it
dash T adds an identifier to the log so that
we'll know that these messages belong to a program called my
app. And dash P sets the priority of the message to info.
In other words,
it tells the system logger that this is a
regular status message and the app is behaving normally.
The next line makes our fake application, wait for five seconds.
We basically simulate that it's working correctly during this time.
Finally, on the last line, the priority of the log message will be set to error.
This tells the system logger that the app encountered some sort of problem.
And the logger will highlight this with the red color, making the message stand out.
So now we simulate that the app encountered an error after five seconds as it exits,
it will print out that error message.
So let's save our file and continue.
We'll make this script executable with the following command.
So how do we create a systemd service?
Well,
we can get some help from the manual describing system
D service files with the help of this command.
We'll see two interesting sections in this manual. First, the options section
here, we will find configuration options for the service we'll define.
Let's take a look at some of the options we'll use.
For example, the restart option here
with this, we can tell system D when it should restart our application
note the values we can assign,
we can pick node to tell system D to never restart it
or on failure to only restart it when the app throws an error code.
But our simple app is not complex enough to throw any error codes.
So we'll just set this to always,
to tell system D to always restart our app when it exits.
If we scroll back up we'll see this restart sec option
which fits well with the previous one
with it,
we can tell system D to wait a while
before attempting to restart an application that stopped running.
In our case, our app will wait five seconds before it exits.
So we wouldn't even need this delay.
But a real world application could potentially fail
and exit in just a few milliseconds.
And if system D would restart it instantly,
it could create an issue where the application
would restart hundreds of times a minute.
This is called a restart loop. And it's something that can slow the system down
by making system D wait a few seconds before restarting the application.
We can avoid such issues.
Finally, if we scroll down on this manual, we'll find the examples section
here. In example two, we can see the simplest system D service we can create,
which is very useful to get an idea about how this file should be structured.
We can see that we need three sections, unit service and install.
We'll see what these do when we create our service.
But for now, let's exit the manual.
As beginners, it would be pretty hard to define a service starting from nothing.
We don't know the exact text that we need.
But we can get some help with this trick
in the directory, live system D system, we'll find already existing service,
unit files so we can use something from that location to get a good
starting point kind of a template on which we can build this from.
Let's copy the service for the SSH daemon.
We'll copy it to a file named
myapp dot Service.
The services that we create should be dropped
into the Etsy system D system directory.
So our copy command will look like this.
And now let's start editing our service file.
Once again, we see the three sections we need to have in a service file, unit,
service and install.
So
let's dive into the unit section
first, we describe this service unit. So let's modify the description.
Now, we don't have a manual for our application.
So let's just remove the second line.
Now, the next line is probably the most important one in the unit section.
This tells system D when it should run this service unit.
And in this case, it's instructed to run it after both the network dot target
and auditd service have started.
Now, a target is basically a collection of services that should start together.
So on this line,
we tell system D to start our service
only when the networking related services have started.
And the audit daemon service.
Now this is vital because most applications
depend on other applications or services.
In this case, the SSH daemon shouldn't start before the network is configured.
Otherwise it won't know what IP address and
network interface to listen to for incoming connections.
So what this does is it basically gathers up some dependencies for your
application and make sure that they're started
and running before your application runs.
But for our purposes, we can just leave this line as it is.
Now on the next line, we can see an exclamation mark which is a symbol for negation.
It's basically like not this.
So this instructs system D to start the service only if this file does not exist.
And we don't need this line for our purposes. So we'll remove it.
But nonetheless,
it's interesting to see how detailed a service file can be in its instructions.
Now, we get to the service section
here, we specify how our application's life cycle should be controlled,
how it should be started,
restarted, reloaded and what should happen when it crashes. And so on,
on the first line, we see an environment file specified
this simply loads environment variables listed in that file like
the path variable that we learned about in previous lessons.
We don't need this line. So we'll remove it
next.
With Execstart Pre,
we can specify a program that should run before our application will be launched.
This can prepare the terrain, so to speak.
For example,
we could run a program that scans the databases
for errors before starting the database server application.
And just to test this out, let's modify it.
We will see this message later in our logs informing us that
the command at Execstart pre was launched before our application was started
finally, we get to the part we're most interested in.
The execstart specifies the command that should be used to start our application.
So let's point this to the location of
our application more specifically our shell script file.
Now,
execreload specifies what should be executed when an
administrator runs the system CTL reload command.
So whenever someone wants to do a
graceful reload to apply modified configuration settings,
this is what will be executed,
we can remove both exact reload lines here. Since our app doesn't support that,
the kill mode line specifies how this application should be stopped.
For example, when an administrator runs a system CTL stop command,
in many cases, a service unit can start multiple processes
or the application run by the service can spawn multiple processes.
So system D has to know how it should stop processes that it started
because of the service
with kill mode equals process.
We tell system D to only kill the main process and
not any child processes that might be launched as well.
In our case, we can leave this as it is.
In other scenarios,
we might set this to kill mode equals control group
which would kill all processes created by the service.
The next line tells system D to only restart our application on failure.
And this is not what we want with our specific app.
When an application exits, it returns an exit code
zero means it exited successfully.
Nonzero means it encountered an error.
Now, our app is simple and it will always exit normally with a zero exit code.
So system D would not restart it with this setting
to restart our application every time it exits, we'll modify this line
and we'll set it to restart. Always.
Also, when we looked at the manual, we explored the restart sec option.
So let's add that
this will add the restart delay that we discussed.
When system D notices our app needs to be restarted,
it will wait one full second before doing so
the next instruction, restart, prevent exit status equals 255.
Tell system D not to restart the service.
If the application throws an exit code equal to 255
and we don't need this so we can remove it as well.
The next line can be important depending on the type of application
here, type equals notify,
tells systemd that the application will notify it when it is finished starting up.
Now, our app does not have such capabilities.
So we'll set this to type equals simple.
Another commonly used option here can be type equals one shot
for applications that don't need to run in the background.
For example, a program that quickly opens up,
deletes some files and then exits because it has nothing else to do.
Another often used option is type equals forking for an
application that spawns many child processes when it's executed.
Now,
the next two lines specify the relative path
to the directory that this application should run in
and the permissions for that directory,
this can be used to create temporary files or whatever the app might need.
However, we'll remove these two lines
and now we get to the install section
to understand the next line. We need to know what systemd targets are.
Normally a server boots up without a graphical user interface,
but multiple users can still log in to a text only interface
to provide this environment where many people can log in
a collection of applications needs to start.
This collection is grouped in what is called the multi
user target.
If the server boots up to a graphical interface,
this is called the graphical target.
And there are many other targets.
Each target is simply a collection of services that
should start up to achieve a certain purpose.
As we saw earlier, the network target groups,
all services needed to have a working network.
With this line,
we tell system D that this service belongs to the target called multiuser.
Next,
the alias line simply instructs system D to create
links to our dot service file in other locations.
The reason for this line here is that the service for managing the SSH daemon
is called SSH D dot service on operating systems from the red hat family,
but on operating systems from the Debian and Ubuntu family,
it's called SSH dot service without the D at the end.
So administrators who are used to typing commands like system CTL reload.
SSH D dot Service would encounter an error on Ubuntu.
But by linking the SSH dot service file here to another file called SSH D dot Service,
both service names will work on
Ubuntu when we want to interact with the SSH daemon.
Now, in our case, we don't need an alias. So we'll remove this line.
Our final service unit file now looks like this.
So let's save our file and see if our service works.
But first when we add, remove or edit service files,
we need to reload the system D daemon with this command.
Now let's take a look at the system log. We'll use the
F option for follow mode so we can see log messages as they're generated
and everything seems to be working perfectly.
So every time our application crashes,
we see the error messages highlighted in a red color
and system D picks it up and restarts it automatically
and let's press control C to exit from following the system log.
Also note that our execstart pre instruction is executing correctly since
we can see the message that we added to that option.
So that wraps up the core concepts around creating a systemd service.
As you can see, it's not really that hard,
just a bunch of instructions in a file.
The hard part is finding the options you need.
But as long as you know what you want system D to do for you.
You'll find all the options you require by typing man,
followed by system D with a dot At the end.
No space and pressing tab twice.
Unfortunately, not all options will be found in the system D dot Service manual.
You'll also find some of them in the system D dot unit manual.
Specifically the stuff you add in the first unit
section of a service file will be found there.
Also some details related to how the application in the service should
be executed will be found in the system D dot exec manual.
And details related to how systemd should stop or kill processes started
by services can be found in the system D dot Kill manual.
But as a beginner,
you might learn faster if you start looking at already made service files.
So start with LS
live
system D slash system
and see how those service files were created
to achieve the purposes of specific applications.
And I hope this was a fun learning experience. I'll see you in the next lesson.