Blog (3)
Komentarze (3)
Recenzje (0)
@mariushkoPoradnik: systemd — cz. 2

Poradnik: systemd — cz. 2

06.11.2015 17:09

Wstęp

Poprzednia część jest tutaj

Kolejność poszukiwania plików unitów

Szczególnym typem unitu jest "service", czyli unit odpowiedzialny za uruchamianie usług. A co jeśli chcemy uruchomić starszą usługę, która nie ma własnego unitu zgodnego z systemd? Możemy to zrobić, ale ma to swoje ograniczenia. Znacznie lepszym pomysłem jest stworzenie dedykowanego dla tej usługi unitu. Systemd zachowuje częściową kompatybilność ze skryptami z rodziny SysV, czyli tymi, które zwyczajowo były umieszczane w /etc/init.d/. Częściową, ponieważ korzystając z nich możemy napotkać problemy następującej natury:

  • mamy ograniczony wpływ na to jakie usługi zostaną uruchomione przed, a jakie po naszej usłudze
  • monitorowanie procesów naszej usługi może być utrudnione
  • zbieranie logów z naszej usługi również może być utrudnione (usługa journald teraz to robi)

Jeśli systemd jest zmuszony uruchomić skrypt "legacy" z /etc/init.d/, to gdy sprawdzimy status tej usługi w opisie usługi zobaczymy "LSB" (Linux Standard Base) i ścieżkę do pliku startowego.

To jest kolejność przeszukiwania katalogów w celu znalezienia pliku unitu:

/run -> /etc ->  /usr -> /etc/init.d

Załóżmy, że chcemy uruchomić serwis o nazwie "abc", wtedy systemd przeszukuje "swoje" katalogi w kolejności:

  • /run - jeśli serwis jest już uruchomiony, to nie trzeba nic robić, koniec
  • /etc - jeśli admin ma swoją wersją, to ona jest uruchamiana, jeśli nie, szukamy dalej
  • /usr - jeśli serwis został dostarczony przez pakiety, to on zostanie uruchomiony
  • /etc/init.d - w ostateczności

Typy serwisów

  1. simple - zwykły proces, który uruchomiony w terminalu nie zwraca znaku zachęty
  2. forking - serwis, który po uruchomieniu "forkuje się" np: apache, a potem działa dalej... (uruchomiony w terminalu przechodzi w tło, odpina się od termianala i zwraca prompt)
  3. oneshot - Jak "simple", ale systemd oczekuje na jego zakończenie, aby kontynuować uruchamianie dalszych/zależnych unitów
  4. dbus - Jak "simple", ale systemd czeka aż serwis podłączy się do D-Bus, potem systemd kontynuuje uruchamianie dalszych/zależnych unitów
  5. notify - Jak "simple", ale systemd czeka aż serwis wyśle wiadomość potwierdzającą zakończenie startu usługi (patrz polecenie: "systemd-notify --ready" ), potem systemd kontynuuje uruchamianie dalszych/zależnych unitów
  6. idle - Jak "simple", ale uruchomienie serwisu zostaje opóźnione do czasu, aż uruchamianie innych usług nie zostaną zakończone

Tworzenie własnych serwisów

Przeczytaj CAŁY rozdział zanim zaczniesz tworzyć własne unity...

Wstęp

Najprostszy serwis:


[Service]
ExecStart=/usr/local/bin/script.sh

Metody zmiany konfiguracji serwisów/unitów:

  1. Kopia z /usr do /etc i poprawiamy plik w /etc - plik w /etc całkowicie zastępuje plik w /usr
  2. W pliku z /etc robimy "include" pliku z /usr i dopisujemy tylko zmiany między nimi
  3. Tworzymy w /etc/ katalog "drop-in" np: name.service.d, a w nim wiele plików "*.conf", które po nałożeniu ich (kolejność jest ważna) na plik serwisu z /usr razem dają docelową konfigurację (zalecany sposób). Podczas sprawdzania statusu takiej usługi, będzie podana lista plików konfiguracyjnych.

Jeśli używamy katalogu "drop-in" i chcemy nadpisać parametr, który może występować wielokrotnie (np: ExecStart=; omówimy te parametry poniżej) w pliku w /usr, to aby poprawnie zastąpić je nową wartością, poprzedzamy nowy wpis pustym wpisem... np:


[Service]
ExecStart=
ExecStart=/new/command

Brzmi skomplikowanie??? Przykład: Co uruchamia sshd.service?


# grep ExecStart= /usr/lib/systemd/system/sshd.service 
ExecStart=/usr/bin/sshd -D

Powiedzmy, że chcesz uruchomić sshd inaczej, np tak:


ExecStart=/usr/bin/sshd -4 -D

Jak to zrobić??? Najprościej: kopiujesz cały /usr/lib/systemd/system/sshd.service do /etc/systemd/system/ i tam dokonujesz zmiany, ale po co się tak dręczyć... Lepiej zrobić tak:


# mkdir /etc/systemd/system/sshd.service.d/
# cat <<EOF > /etc/systemd/system/sshd.service.d/10-Service.conf
[Service]
ExecStart=
ExecStart=/usr/bin/sshd -4 -D
EOF
# systemctl daemon-reload 
# systemctl restart sshd

Zwróć uwagę na wpis "Drop-In":


# systemctl status sshd
  sshd.service - OpenSSH Daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/sshd.service.d
           L 10-Service.conf
   Active: active (running) since czw 2015-11-05 15:12:18 CET; 1s ago
 Main PID: 24028 (sshd)
   CGroup: /system.slice/sshd.service
           L 24028 /usr/bin/sshd -4 -D

lis 05 15:12:18 archer systemd[1]: Stopped OpenSSH Daemon.
lis 05 15:12:18 archer systemd[1]: Started OpenSSH Daemon.
lis 05 15:12:18 archer sshd[24028]: Server listening on 0.0.0.0 port 22.

Polecenie "systemctl edit" ułatwi Ci życie.

Utworzenie katalogu "drop-in" w /etc/systemd/system/name.type.d:

# systemctl edit name.type

Zamiast katalogu drop-in przekopiowanie pliku unitu z /usr /do /etc:

# systemctl edit --full name.type

Zmiany tymczasowe: (konfiguracja pobrana z /run, zginie po restarcie)

# systemctl edit --runtime name.type

Dodatkowe opcje polecenia "systemctl edit":

  • --system (domyślnie) - katalog docelowy to /etc/systemd/system/
  • --user - zwykły użytkownik może zmienić definicję unitów z /usr/lib/systemd/user/ (lub stworzyć nową) umieszczając ją w ${HOME}/.config/systemd/user/
  • --global - root może zmodyfikować środowisko wszystkich użytkowników (/usr/lib/systemd/user/) w katalogu /etc/systemd/user/

Polecenie "systemd-delta" pokazuje wszystkie różnice/powiązania między unitami z /usr a /etc:


# systemd-delta
[EXTENDED]   /usr/lib/systemd/system/libvirtd.socket › /etc/systemd/system/libvirtd.socket.d/99-Install.conf
[EXTENDED]   /usr/lib/systemd/system/libvirtd.socket › /etc/systemd/system/libvirtd.socket.d/50-Socket.conf
[EQUIVALENT] /etc/systemd/system/default.target › /usr/lib/systemd/system/default.target
[EXTENDED]   /usr/lib/systemd/system/sshd.service › /etc/systemd/system/sshd.service.d/10-Service.conf

Czy mogę teraz zobaczyć za jednym zamachem całość konfiguracji ssh.service?:


$ systemctl cat sshd.service 
# /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH Daemon
Wants=sshdgenkeys.service
After=sshdgenkeys.service
After=network.target

[Service]
ExecStart=/usr/bin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

# This service file runs an SSH daemon that forks for each incoming connection.
# If you prefer to spawn on-demand daemons, use sshd.socket and sshd@.service.

# /etc/systemd/system/sshd.service.d/10-Service.conf
[Service]
ExecStart=
ExecStart=/usr/bin/sshd -4 -D

Czyli wiemy już JAK zmieniać ustawienia, pytanie: CO możemy zmieniać?

Przykładowy serwis

Przykład usługi wykorzystującej plik modyfikujący środowisko aplikacji oraz jawną deklarację nowej zmiennej:


[Service]
Environment=MY_OPTION=1410
EnvironmentFile=/etc/sysconfig/myapp.conf
ExecStart=/path/myapp $OPTION_FROM_FILE $MY_OPTION

Opcje:

  • ExecStartPre= - polecenie te zostanie uruchomione przed ExecStart (można używać wielokrotnie)
  • ExecStart= - główne polecenie uruchamiające naszą aplikację (można używać wielokrotnie, ale tylko w "oneshot")
  • ExecStartPost= - polecenie te zostanie uruchomione po zakończeniu uruchamiania wszystkich ExecStart (można używać wielokrotnie)
  • ExecReload= - polecenie te zostanie uruchomione, gdy wykonamy "systemctl reload name.service"
  • ExecStop= - polecenie te zostanie uruchomione, gdy wykonamy "systemctl stop foo.service" (można używać wielokrotnie)
  • ExecStopPost= - polecenie te zostanie uruchomione niezależnie, czy ExecStop= był zdefiniowany i wykonany, a także w przypadku niespodziewanego zakończenia ExecStart= (można używać wielokrotnie)
  • Restart= - określa, czy i kiedy usługa ma być restartowana. Przyjmuje wartości: "no" (domyślnie), "on-success", "on-failure", "on-abnormal", "on-watchdog", "on -abort", "always"
  • RestartSec=- czas po którym usługa zostanie uruchomiona ponownie (zabezpiecza zepsuty serwis przed próbami restartu co 100ms)
  • SuccessExitStatus= - jeśli aplikacja nie ma w zwyczaju kończyć się kodem wyjścia 0, tylko 5, to możemy powiedzieć, że 5 jest ok :)
  • OnFailure= - lista (oddzielona spacjami) unitów, która zostanie aktywowana po awarii unitu
  • PidFile= - jeśli serwis ma własny plik z PIDami swoich procesów, można skazać ten plik
  • TimeoutStartSec= - po jakim maksymalnie czasie od uruchomienia serwis powinien być gotowy do pracy (default=90) - jeśli nie jest, zostanie ubity
  • RemainAfterExit= - "yes" - jeśli chcemy aby systemd uważał, że po zakończeniu działania serwis jest ciągle uruchomiony

Czas na konkrety...

Utwórz trzy pliki: testowy skrypt, plik konfiguracyjny i testową usługę:


# cat /etc/myscript.conf 
OPTION_FROM_FILE=666

# cat /usr/local/bin/myscript.sh 
#!/bin/bash
echo "$@"

# cat /etc/systemd/system/myscript.service 
[Unit]
Description=Moj kozacki skrypt

[Service]
# Type=oneshot
Environment=MY_OPTION=1410
EnvironmentFile=/etc/myscript.conf

ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 1 $OPTION_FROM_FILE $MY_OPTION
ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 2 $OPTION_FROM_FILE $MY_OPTION
ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 3 $OPTION_FROM_FILE $MY_OPTION
ExecStart=/usr/local/bin/myscript.sh ExecStart= 1 $OPTION_FROM_FILE $MY_OPTION
# ExecStart=/usr/local/bin/myscript.sh ExecStart= 2 $OPTION_FROM_FILE $MY_OPTION
# ExecStart=/usr/local/bin/myscript.sh ExecStart= 3 $OPTION_FROM_FILE $MY_OPTION
ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 1 $OPTION_FROM_FILE $MY_OPTION
ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 2 $OPTION_FROM_FILE $MY_OPTION
ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 3 $OPTION_FROM_FILE $MY_OPTION
ExecStop=/usr/local/bin/myscript.sh ExecStop= 1
ExecStop=/usr/local/bin/myscript.sh ExecStop= 2
ExecStop=/usr/local/bin/myscript.sh ExecStop= 3
ExecStopPost=/usr/local/bin/myscript.sh ExecStopPost= 1
ExecStopPost=/usr/local/bin/myscript.sh ExecStopPost= 2
ExecStopPost=/usr/local/bin/myscript.sh ExecStopPost= 3
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

# chmod +x /etc/systemd/system/myscript.service

# ls -al /etc/myscript.conf /usr/local/bin/myscript.sh /etc/systemd/system/myscript.service 
-rw-r--r-- 1 root root   21 11-06 12:02 /etc/myscript.conf
-rw-r--r-- 1 root root 1254 11-06 12:24 /etc/systemd/system/myscript.service
-rwxr-xr-x 1 root root   23 11-06 11:50 /usr/local/bin/myscript.sh

Teraz możemy uruchomić usługę myscript.service:


# systemctl daemon-reload 
# systemctl start myscript
# systemctl status myscript -l
 myscript.service - Moj kozacki skrypt
   Loaded: loaded (/etc/systemd/system/myscript.service; disabled; vendor preset: disabled)
   Active: active (exited) since pią 2015-11-06 12:38:45 CET; 7s ago
  Process: 32458 ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 3 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32455 ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 2 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32452 ExecStartPost=/usr/local/bin/myscript.sh ExecStartPost= 1 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32451 ExecStart=/usr/local/bin/myscript.sh ExecStart= 1 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32448 ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 3 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32445 ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 2 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
  Process: 32442 ExecStartPre=/usr/local/bin/myscript.sh ExecStartPre= 1 $OPTION_FROM_FILE $MY_OPTION (code=exited, status=0/SUCCESS)
 Main PID: 32451 (code=exited, status=0/SUCCESS)

lis 06 12:38:45 archer systemd[1]: Starting Moj kozacki skrypt...
lis 06 12:38:45 archer myscript.sh[32442]: ExecStartPre= 1 666 1410
lis 06 12:38:45 archer myscript.sh[32445]: ExecStartPre= 2 666 1410
lis 06 12:38:45 archer myscript.sh[32448]: ExecStartPre= 3 666 1410
lis 06 12:38:45 archer myscript.sh[32451]: ExecStart= 1 666 1410
lis 06 12:38:45 archer myscript.sh[32452]: ExecStartPost= 1 666 1410
lis 06 12:38:45 archer myscript.sh[32455]: ExecStartPost= 2 666 1410
lis 06 12:38:45 archer myscript.sh[32458]: ExecStartPost= 3 666 1410
lis 06 12:38:45 archer systemd[1]: Started Moj kozacki skrypt.

A teraz możemy wyłączyć usługę myscript.service:


[root@archer system]# systemctl stop myscript
[root@archer system]# systemctl status myscript -l
 myscript.service - Moj kozacki skrypt
   Loaded: loaded (/etc/systemd/system/myscript.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

lis 06 12:38:45 archer myscript.sh[32458]: ExecStartPost= 3 666 1410
lis 06 12:38:45 archer systemd[1]: Started Moj kozacki skrypt.
lis 06 12:39:05 archer systemd[1]: Stopping Moj kozacki skrypt...
lis 06 12:39:05 archer myscript.sh[32469]: ExecStop= 1
lis 06 12:39:05 archer myscript.sh[32472]: ExecStop= 2
lis 06 12:39:05 archer myscript.sh[32474]: ExecStop= 3
lis 06 12:39:05 archer myscript.sh[32479]: ExecStopPost= 1
lis 06 12:39:05 archer myscript.sh[32482]: ExecStopPost= 2
lis 06 12:39:05 archer myscript.sh[32486]: ExecStopPost= 3
lis 06 12:39:05 archer systemd[1]: Stopped Moj kozacki skrypt.

Gratuluję!!! Właśnie odpaliłeś swój pierwszy serwis typu "simple" :) Jako zadanie domowe "odkomentuj" trzy "zakomentowane" linie w myscript.service i sprawdź, jak działa serwis typu "oneshot".

Uruchamianie warunkowe

Jeśli nasza usługa wymaga zamontowanego systemu plików, to dodajemy to wymaganie do naszego serwisu - wpływa to na kolejność uruchamiania usług i musi być spełnione:


[Unit]
RequiresMountsFor=/var/tmp

A co jeśli chcemy przed uruchomieniem coś sprawdzić i zależnie od wyniku uruchomić usługę??? Czyli uruchomić ją tylko wtedy, gdy jakieś warunki będą spełnione... Warunkowe uruchamianie na przykładzie /lib/systemd/system/sshdgenkeys.service:


[Unit]
Description=SSH Key Generation
ConditionPathExists=|!/etc/ssh/ssh_host_key
ConditionPathExists=|!/etc/ssh/ssh_host_key.pub
ConditionPathExists=|!/etc/ssh/ssh_host_rsa_key
ConditionPathExists=|!/etc/ssh/ssh_host_rsa_key.pub
ConditionPathExists=|!/etc/ssh/ssh_host_dsa_key
ConditionPathExists=|!/etc/ssh/ssh_host_dsa_key.pub

[Service]
ExecStart=/usr/bin/ssh-keygen -A
Type=oneshot
RemainAfterExit=yes

Jak to rozumieć? Najpierw pokażmy jeszcze kilka (man systemd.unit) innych warunków:

  • ConditionPathExists= - czy istnieje tak ścieżka (plik. katalog, link,..., cokolwiek)
  • ConditionPathIsDirectory= - czy istnieje katalog
  • ConditionPathIsSymbolicLink= - czy istnieje symboliczny link
  • ConditionPathIsMountPoint= - czy istnieje punkt montowania
  • ConditionPathIsReadWrite= - czy można modyfikować system plików, na którym znajduje się wskazany obiekt
  • ConditionDirectoryNotEmpty= - czy katalog istnieje i jest niepusty
  • ConditionFileNotEmpty= - czy plik istnieje i jest niepusty
  • ConditionFileIsExecutable= - czy istnieje plik i ma ustawiony atrybut "eXecutable"

Wszystkie warunki muszą być spełnione (AND):


Condition*=WARUNEK1
Condition*=WARUNEK2
Condition*=WARUNEK3

Jeśli chcemy aby conajmniej jeden był spełniony, dodajemy "|" (OR):


Condition*=|WARUNEK1
Condition*=|WARUNEK2
Condition*=|WARUNEK3

Negację: (not AND): i not OR )


Condition*=!WARUNEK1
Condition*=!WARUNEK2
Condition*=!WARUNEK3

Negację: (not OR):


Condition*=|!WARUNEK1
Condition*=|!WARUNEK2
Condition*=|!WARUNEK3

Zatem nasz przykład:


ConditionPathExists=|!/etc/ssh/ssh_host_key
ConditionPathExists=|!/etc/ssh/ssh_host_key.pub
ConditionPathExists=|!/etc/ssh/ssh_host_rsa_key
ConditionPathExists=|!/etc/ssh/ssh_host_rsa_key.pub
ConditionPathExists=|!/etc/ssh/ssh_host_dsa_key
ConditionPathExists=|!/etc/ssh/ssh_host_dsa_key.pub

oznacza, że usługa ta zostanie uruchomiona, jeśli zabraknie chociaż jednego z tych plików...

Zależności

Przykład: /usr/lib/systemd/system/sshd.service


[Unit]
Description=OpenSSH Daemon
Wants=sshdgenkeys.service
After=sshdgenkeys.service
After=network.target

[Service]
ExecStart=/usr/bin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target
  • Requires= - jeśli nasz unit zostanie włączony, to wymienione tu unity zostaną włączone również. Jeśli któryś z nich przestanie działać, nasz unit również. Nie mamy wpływu na kolejność włączania i wyłączania. Jeśli chcesz mieć wpływ na kolejność użyd dodatkowo opcji: After= lub/i Before= - bez nich unity zostaną uruchomione równolegle i bez żadnych opóźnień. Opcja Wants= jest bardziej elastyczna...
  • Wants= - wymienione tu unity będą uruchomione, jeśli są przewidziane do startu (enabled). Nasz unit wystartuje poprawnie, jeśli nawet któryś z wymienionych unitów nie włączy się poprawnie. Zalecany sposób na wskazanie zależności między unitami.
  • BindsTo= - jak Wants=, ale jeśli któryś z wymienionych unitów przestanie działać, również nasz unit przestaje działać...
  • Conflicts= - lista unitów które zostaną wyłączony, gdy nasz unit zostanie włączony. Opcje: After= i Before= mają zastosowanie.
  • Before=, After= - wskazanie kolejności uruchamiania unitów, które są przeznaczone do uruchomienia
  • PartOf= - przypinamy się do unita, czyli podczas zatrzymywania go lub restartu nasz unit robi to samo, ale jest to relacja jednostronna.

Template

Co to jest "template"? Czyli jak przekazać parametr do unitu...

1. W systemie mamy zwykle wirtualne konsole od tty1 do tty6. Warto tworzyć 6 serwisów o prawie tej samej treści? 2. Od czasu do czasu (np: przy starcie systemu) trzeba sprawdzać (fsck) spójność systemu plików, często wielu. Jak wskazać który? 3. Może chcesz uruchomić np: SSHD,vsftpd,vpnc na konkretnym adresie IP? Jak wskazać na którym IP? 4. Może potrzebujesz uruchomić klienta DHCP na konkretnym interfejsie sieciowym? Jak wskazać na którym?

Jak wygląda "template"? Template to plik unitu o nazwie:

name@.type

np: /usr/lib/systemd/system/getty@.service Nie możesz jednak po prostu uruchomić serwisu "getty@.service"!!!

Sprawdźmy jak radzi sobie "target" getty.


# ls -al /etc/systemd/system/getty.target.wants/
razem 8
drwxr-xr-x 2 root root 4096 06-23 12:13 .
drwxr-xr-x 9 root root 4096 08-12 14:16 ..
lrwxrwxrwx 1 root root   38 06-23 12:13 getty@tty1.service -> /usr/lib/systemd/system/getty@.service

Sprawdźmy, czy faktycznie usługa getty@tty1.service jest uruchomiona:


 # systemctl status getty@tty1.service
 getty@tty1.service - Getty on tty1
   Loaded: loaded (/usr/lib/systemd/system/getty@.service; enabled; vendor preset: enabled)
   Active: active (running) since pon 2015-08-10 18:48:36 CEST; 2 days ago

Zatem jeśli chcemy wykorzystać "template" musimy po znaku '@' podać parametr (nazwa instancji).

Co mamy we wzorcu?


# grep Exec /lib/systemd/system/getty@.service
ExecStart=-/sbin/agetty --noclear %I $TERM

Parametr %I (patrz: man systemd.unit) to właśnie nazwa instancji, zatem wywołanie usługi getty@tty3.service spowoduje wykonanie polecenia:


ExecStart=-/sbin/agetty --noclear tty3 $TERM

Sprawdźmy:


# ps -eo tty,command | grep '^tty1 '
tty1     /sbin/agetty --noclear tty1 linux

Sprawa trochę jest trudniejsza, jeśli nasza nazwa instancji ma postać np: ścieżki do pliku lub urządzenia.

Weźmy ten przykład (w bashu znak ucieczki, "escape character", to '\', więc "\\" znaczy '\')


# systemctl | grep systemd-fsck
systemd-fsck@dev-disk-by\x2dlabel-DATA.service   loaded active exited    File System Check on /dev/disk/by-label/DATA
# systemctl cat systemd-fsck@dev-disk-by\\x2dlabel-DATA.service | grep Exec
ExecStart=/usr/lib/systemd/systemd-fsck %f

Czyli nazwa instancji to: 'dev-disk-by\x2dlabel-DATA'. "Odszyfrowanie" ścieżki:


# systemd-escape -p --unescape 'dev-disk-by\x2dlabel-DATA'
/dev/disk/by-label/DATA

"Zaszyfrowanie" ścieżki:


$ systemd-escape -p /dev/disk/by-label/DATA
dev-disk-by\x2dlabel-DATA

Zatem w naszym przykładzie (%f = "odszyfrowana" ścieżka) polecenie do uruchomienia usługa ma postać:


ExecStart=/usr/lib/systemd/systemd-fsck /dev/disk/by-label/DATA

Poznaliśmy zmienne/parametry %I i %f, ale jest ich dużo więcej - patrz: man systemd.unit.

Podsumowanie

Potrafimy już napisać prosty serwis i mamy już pojęcie o tym, jak można to skomplikować.

Wkrótce następne części telenoweli - stay tuned :)

Wybrane dla Ciebie
Komentarze (4)