mirror of
https://github.com/foo-dogsquared/wiki.git
synced 2025-01-31 10:58:28 +00:00
7c75fc2531
Was able to finally pass through the ArgoCD installation among other things. I also updated more exercises to tangle my solutions into a file.
274 lines
8.6 KiB
Org Mode
274 lines
8.6 KiB
Org Mode
#+title: Exploring systemd features
|
|
#+date: "2021-05-20 22:37:22 +08:00"
|
|
#+date_modified: "2021-07-01 11:54:34 +08:00"
|
|
#+language: en
|
|
#+property: header-args :eval no
|
|
|
|
|
|
systemd is a big tool for a big system.
|
|
Let's explore some of them from a perspective of a wannabe power user.
|
|
|
|
|
|
|
|
|
|
* systemd at user-level
|
|
|
|
systemd has the ability to run at user-level empowering the user to manage their own system with their own settings.
|
|
It immensely helps separating user-specific settings from the system-wide settings.
|
|
|
|
systemd looks for the units from certain paths.
|
|
You can look for them from the =systemd.unit.5= manual page.
|
|
|
|
To run systemd as a user instance, simply add a =--user= flag beforehand for =systemctl= and other systemd binaries, if applicable.
|
|
|
|
#+begin_src shell :results none
|
|
# See how different the output when run at user- and system-level.
|
|
systemctl --user show-units
|
|
systemctl show-units
|
|
|
|
systemctl --user show-environment
|
|
systemctl show-environment
|
|
|
|
systemctl --user start $SERVICE
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
* Timers as cron replacement
|
|
|
|
You can schedule tasks with timers.
|
|
If systemd is compiled with the feature, it makes cron unnecessary.
|
|
|
|
systemd has different ways to denote time.
|
|
|
|
- Timespans denote the duration — e.g., =100 seconds=, =5M 3w=.
|
|
- Timestamps refer to a specific point in time — e.g., =2021-04-02=, =today=, =now=.
|
|
- Calendar events can refer to more than one point of time — e.g., =*-*-4/2=, =Sun,Wed,Fri *-1/2-1/8=.
|
|
|
|
Here's an example of setting a timer for an example backup service.
|
|
The following timer unit sets it to execute every day at 18:00.
|
|
|
|
#+begin_src ini
|
|
[Unit]
|
|
Description=A deduplicated backup from my computer
|
|
Documentation=man:borg(1) https://borgbackup.readthedocs.io/
|
|
|
|
[Timer]
|
|
Unit=borg-backup.service
|
|
OnCalendar=*-*-* 18:00:00
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=graphical.target
|
|
#+end_src
|
|
|
|
This will trigger =borg-backup.service= from the load path.
|
|
But you can omit it if you named the timer unit file similarly (e.g., =borg-backup.timer= with =borg-backup.service=).
|
|
|
|
You can find more information about it from the =systemd.time.5= manual page.
|
|
Furthermore, systemd has a testing tool for time with ~systemd-analyze {timespan,timestamp,calendar}~.
|
|
|
|
#+begin_src shell :eval yes
|
|
printf "Timespan example:\n"
|
|
printf "..............\n"
|
|
systemd-analyze timespan 4000min
|
|
printf "..............\n\n"
|
|
|
|
printf "Timestamp example:\n"
|
|
printf "..............\n"
|
|
systemd-analyze timestamp 2021-07-01
|
|
printf "..............\n\n"
|
|
|
|
printf "Calendar example:\n"
|
|
printf "..............\n"
|
|
systemd-analyze calendar "*-1/4-5 0/2:00:00"
|
|
printf "..............\n\n"
|
|
#+end_src
|
|
|
|
#+results:
|
|
#+begin_example
|
|
Timespan example:
|
|
..............
|
|
Original: 4000min
|
|
μs: 240000000000
|
|
Human: 2d 18h 40min
|
|
..............
|
|
|
|
Timestamp example:
|
|
..............
|
|
Original form: 2021-07-01
|
|
Normalized form: Thu 2021-07-01 00:00:00 PST
|
|
(in UTC): Wed 2021-06-30 16:00:00 UTC
|
|
UNIX seconds: @1625068800
|
|
From now: 11h ago
|
|
..............
|
|
|
|
Calendar example:
|
|
..............
|
|
Original form: *-1/4-5 0/2:00:00
|
|
Normalized form: *-01/4-05 00/2:00:00
|
|
Next elapse: Sun 2021-09-05 00:00:00 PST
|
|
(in UTC): Sat 2021-09-04 16:00:00 UTC
|
|
From now: 2 months 4 days left
|
|
..............
|
|
|
|
#+end_example
|
|
|
|
|
|
|
|
|
|
* Unit templates
|
|
|
|
You can create unit templates which is useful for simple services that only requires an argument.
|
|
Rather than creating individual simple service files, let systemd handle it.
|
|
|
|
For example, you may want to spawn a service for Borgmatic with multiple repos.
|
|
If you don't know templates, the dumb way to serve multiple repos is to create individual unit files for each.
|
|
If you want to schedule them, you also have to create a timer unit for each.
|
|
|
|
The more efficient solution is to use templates.
|
|
To make a unit template, there are only a handful of requirements:
|
|
|
|
- Addition of =%i= to represent the template value.
|
|
- The unit file name has to end with =@= (e.g., =unit-name@.service=, =unit-name@.timer=).
|
|
|
|
This could be compressed into a template for a service unit.
|
|
The following code shows how to create one.
|
|
|
|
#+begin_src ini
|
|
[Unit]
|
|
Description=Periodic safety backup for %i
|
|
Documentation=man:borg(1) https://www.borgbackup.org/
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=borgmatic --config %i --verbose
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|
|
|
|
To use the service, you have to give it a value — e.g., ~systemctl --user start borg-backup@test.yaml.service~.
|
|
|
|
That's all good but what about scheduling them?
|
|
What if you want to create an archive every hour starting at 08:00?
|
|
You can just create a templated timer unit.
|
|
|
|
#+begin_src ini
|
|
[Unit]
|
|
Description=Periodic safety backup for %i
|
|
Documentation=man:borg(1) https://www.borgbackup.org/
|
|
|
|
[Timer]
|
|
Unit=borg-backup@%i.service
|
|
Calendar=08/1:00:00
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
* Transient units
|
|
|
|
You can create units on-the-go with =systemd-run=.
|
|
It generates transient unit files.
|
|
Though, this is oriented around service units, making it useful for one-time configurations and task scheduling.
|
|
|
|
Like most systemd-related binaries, this can configure in system- and user-level.
|
|
|
|
#+begin_src shell
|
|
# This will create a user-level service file with the given command as the task.
|
|
systemd-run --user borgmatic --config emergency-config.yaml --verbose
|
|
|
|
# Create a transient timer for the service.
|
|
systemd-run --user borg-backup@external-drive.service --on-calendar=12:00
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
* Service management
|
|
|
|
One of the functions of the system suite is service management.
|
|
Like most of the components, it can be used at user-level with their set locations, managing the service daemon, and all.
|
|
|
|
Just plop down a service unit file at one of the search paths and you can start managing right away.
|
|
For more information, see the manual page (i.e., =systemd.service.5=).
|
|
A summarized version can be found at [[Service configuration]].
|
|
|
|
Here's an example of a user service resided as =$HOME/.config/systemd/user/drive-backup.service=.
|
|
|
|
#+begin_src ini
|
|
[Unit]
|
|
Description=Periodic safety backup for my external drive
|
|
Documentation=man:borg(1) https://www.borgbackup.org/ https://torsion.org/borgmatic/
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=%h/.nix-profile/bin/borgmatic --config %h/dotfiles/borgmatic/personal-drive.yaml --verbosity 2 create
|
|
ExecStart=%h/.nix-profile/bin/borgmatic --config %h/dotfiles/borgmatic/personal-drive.yaml --verbosity 2 prune
|
|
ExecStart=%h/.nix-profile/bin/borgmatic --config %h/dotfiles/borgmatic/personal-drive.yaml --verbosity 2 check
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|
|
|
|
You can then start the service with:
|
|
|
|
#+begin_src shell :eval no
|
|
systemctl --user start drive-backup.service
|
|
#+end_src
|
|
|
|
You can also stop it with the =stop= subcommand (e.g., ~systemctl --user stop drive-backup.service~) and restart it with =restart= (e.g., ~systemctl --user restart drive-backup.service~).
|
|
|
|
If you want to enable it at startup, you can go with =enable= subcommand.
|
|
(To disable it, use the =disable= subcommand.)
|
|
|
|
#+begin_src shell :eval no
|
|
systemctl --user enable drive-backup.service
|
|
#+end_src
|
|
|
|
systemd will use the configuration file as-is by the time it is started/enabled.
|
|
Which means if the config file has been modified after activation, it will not take effect until you restarted it.
|
|
For this, you can reload the daemon with =daemon-reload= subcommand.
|
|
But for simpler cases, you can use the =reload= subcommand without fully restarting the daemon.
|
|
|
|
#+begin_src shell :eval no
|
|
systemctl --user reload drive-backup.service
|
|
|
|
# You could also use...
|
|
# systemctl --user daemon-reload
|
|
# ...if you need a stronger option.
|
|
#+end_src
|
|
|
|
|
|
** Service configuration
|
|
|
|
There are different types of services.
|
|
|
|
- The most common type of service is =simple= which considers the unit active after the main process is forked (e.g., =Service.ExecStart=).
|
|
This is the recommended type for long-running processes.
|
|
|
|
- =oneshot= marks the service resolved after the main process exits.
|
|
Due to the behavior, it will directly go from activating to deactivating instead of active.
|
|
|
|
- =exec= considers the service active after the binary has been executed.
|
|
|
|
Aside from types, each service may have one or more commands although the behavior is set depending on the type.
|
|
|
|
- =ExecStart= which is usually the main command and most services will throw an error if it's missing.
|
|
All services, unless specified as a =oneshot= service, only have one of these values.
|
|
|
|
- =ExecStop= only executes after the main command successfully starts.
|
|
|
|
- =ExecStartPre= and =ExecStartPost= gives you additional commands that will be executed before and after the main command, respectively.
|
|
|
|
- =ExecStopPre= and =ExecStopPost= is similar to the pre- and post-start commands except for the stop command.
|
|
|
|
- =Reload= sets whether the service restarts on fail.
|
|
Values accepted are =no=, =on-failure=, and =on-success=.
|