Blog (3)
Komentarze (3)
Recenzje (0)

Poradnik: systemd — cz. 2

@mariushkoPoradnik: systemd — cz. 206.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 :)

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.