This post is for server-side Swift developers.
All apps on a server need to be launched under some watchdog daemon. You might already be using supervisord
or systemd
.
This article will show you how to simplify your life with systemd
by integrating it directly into your app.
First, let's look at how we usually work with systemd
and the steps needed to set up a service.
Pure systemd
Setting Up
Create a unit configuration file manually by searching for examples online and saving it in the /etc/systemd/system
folder.
Not so easy, right? Most people give up somewhere around here.
Management
You have to remember a few simple commands:
systemctl start myapp.service
restart myapp.service
stop myapp.service
But also the name you gave your service π
Don't forget to start your app after creating the unit configuration file.
If You Want to Remove the Service
systemctl stop myapp.service
systemctl start clean --all
Not too hard to remember, but still...
Logs
This is where most people get lost, because logs can either be stored in some .log
files somewhere in the system, or you have to use journalctl
commands like these:
For live logs:
journalctl -u myapp -f
For the last few log lines:
journalctl -u myapp -n 100 --no-pager
I believe it's a bit hard to remember, and I often use the
up-arrow
in the console to find the right command from history.
π° The Swift Plugin Way
SwiftSystemd to the rescue!
It provides a simple way to handle all the above without headaches.
β‘οΈ Installation
Open your app's Package.swift
and add just one line:
.package(url: "https://github.com/MihaelIsaev/SwiftSystemd.git", from:"1.0.0")
After that, you're ready to go!
π οΈ Setting Up
Let's see how to create a proper unit configuration file for systemd
. In the folder with your app, just run:
swift run systemd install
It will prompt you with a few questions in the console, and then you're done.
Or you can specify the answers in advance like this:
swift run systemd install -c release -t App -u mike
where
-c
or --config
is for configuration: release
or debug
-t
or --target
is for Executable target name
-u
or --user
is for user under which the service will run
This command generates the following unit config file:
[Unit]
Description="AppName"
After=network.target
[Service]
User={user}
EnvironmentFile=/path/to/AppName/.env
WorkingDirectory=/path/to/AppName
TimeoutStopSec=2
Restart=always
ExecStart=/path/to/AppName/.build/{config}/{target}
[Install]
WantedBy=multi-user.target
That's it! You've set up your app the right way in just two simple steps, and it's already running.
π Logs
One of the most essential tasks is watching logs, and it's as easy as:
swift run systemd logs
This displays live logs of your app via journalctl
.
swift run systemd logs --limit 100
This shows the last 100
lines from your app's log via journalctl
Easy to remember!
ποΈ Management
You can check the app's status by running:
swift run systemd status
Or manage the app state with the following commands:
swift run systemd start # starts the app
stop # stops the app
restart # restart the app
disable # temporarily disables the app
enable # re-enables the app
You can also send a kill
signal to the app:
swift run systemd kill
π§Ή Cleaning Up
If you no longer need the service, you can remove it easily:
swift run systemd uninstall
This deletes the systemd
configuration file and stops the service if it's still active.
π Conclusion
I believe you can now throw away all your systemctl
and journalctl
notes, just like I did!
β€οΈ Feel free to contribute!
Top comments (0)