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

Poradnik: systemd — cz. 3

10.11.2015 18:07, aktualizacja: 17.11.2015 10:56

Wstęp

Kontynuacja dwóch poprzednich części: 1 i 2.

Uruchamianie poleceń

Już ustaliliśmy, że najprostszy serwis to:


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

Pytanie: a jeśli potrzebuje uruchomić jakieś polecenie tylko raz, to czy muszę tworzyć plik serwisu? Nie... Tak wygląda polecenie "ls /root" uruchomione bezpośrednio w systemd:


# systemd-run ls /root
Running as unit run-18402.service.

# systemctl status -l run-18402.service
  run-18402.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)

lis 10 14:33:35 archer systemd[1]: Started /usr/bin/ls /root.
lis 10 14:33:35 archer ls[18407]: docker.iptables
lis 10 14:33:35 archer ls[18407]: lista.org
lis 10 14:33:35 archer ls[18407]: lista.txt

Jeden z plusów uruchomienia jakiegoś skryptu lub polecenia jako unitu jest fakt, że możemy teraz korzystać z własności systemd - m.in. przejrzeć log:


# journalctl -u run-18402.service
-- Logs begin at wto 2015-06-23 13:50:59 CEST, end at wto 2015-11-10 14:33:35 CET. --
lis 10 14:33:35 archer systemd[1]: Started /usr/bin/ls /root.
lis 10 14:33:35 archer ls[18407]: docker.iptables
lis 10 14:33:35 archer ls[18407]: lista.org
lis 10 14:33:35 archer ls[18407]: lista.txt
lis 10 14:33:35 archer ls[18407]: plik
lis 10 14:33:35 archer ls[18407]: plik1
lis 10 14:33:35 archer ls[18407]: plik2
lis 10 14:33:35 archer ls[18407]: plik.sh
lis 10 14:33:35 archer ls[18407]: yyy.txt

To chyba dobry czas, by powiedzieć sobie parę zdań o journald.

Logowanie - journald

Systemd zawiera usługę odpowiedzialną za zbieranie logów. W systemach Red Hat w celu utrzymania kompatybilności równolegle działa usługa "rsyslog". W Arch Linux możesz spokojnie skupić się na "journald", a dokładnie na usłudze "systemd-journald". Journald przechowuje logi w postaci binarnej i domyślnie są przechowywane w ulotnym katalogu /run, czyli giną podczas restartu maszyny... Możemy równolegle przechowywać je - jak robi Red Hat - w "rsyslogu", albo zrobić tak:


# mkdir /var/log/journal/
# chgrp systemd-journal /var/log/journal/
# chmod 2755 /var/log/journal/
# killall -USR1 systemd-journald

Przeglądamy log poleceniem:


# journalctl

Ostatnie 10 lub N linii:


# journalctl -n [N]

Pokaż logi o priorytecie "err" (priorytety jak w rsyslog):


# journalctl {-p|--priority} err

Monitorowanie logu w trybie ciągłym - coś jak "tail -f":


# journalctl -f

Logi od dnia [do dnia]:


# journalctl --since "2014-02-10 20:30:00"
# journalctl --since "2014-02-10 20:30:00" --until "2014-02-11 20:30:00"
# journalctl --since {yesterday,today,tomorrow}

Logi w journal nie są "płaskie", jak w rsyslogu. Dodaj opcję "‑o verbose" a zobaczysz, iż wpisy w journald mają postać rekordu:


# journalctl -n 1 -o verbose
-- Logs begin at wto 2015-06-23 13:50:59 CEST, end at wto 2015-11-10 14:33:35 CET. --
wto 2015-11-10 14:33:35.842591 CET [s=52fe4d852ffc4d83bd7ba37d30b85d68;i=18b6e;b=4e42413b402a4241b59d6b665776c144;m=11daf8b02b0;t=5242fc1ba8751;x=847c4d27c2cb86c8]
    _TRANSPORT=syslog
    _SYSTEMD_SLICE=system.slice
    _MACHINE_ID=998523018d824208a4de0c4af4f2fbd8
    _HOSTNAME=archer
    _CAP_EFFECTIVE=0
    PRIORITY=5
    SYSLOG_FACILITY=10
    SYSLOG_IDENTIFIER=polkitd
    _UID=102
    _GID=102
    _COMM=polkitd
    _EXE=/usr/lib/polkit-1/polkitd
    _CMDLINE=/usr/lib/polkit-1/polkitd --no-debug
    _SYSTEMD_CGROUP=/system.slice/polkit.service
    _SYSTEMD_UNIT=polkit.service
    _BOOT_ID=4e42413b402a4241b59d6b665776c144
    SYSLOG_PID=569
    _PID=569
    MESSAGE=Unregistered Authentication Agent for unix-process:18402:122701076 (system bus name :1.270, object path /org/freedesktop/PolicyKit1/AuthenticationAgent, locale pl_PL.utf8) (disconnected from bus)
    _SOURCE_REALTIME_TIMESTAMP=1447162415842591

Czyli dla każdego wpisu do logu mamy informacje o jego pochodzeniu i kontekscie. Wynik tego polecenia zawiera pola m.in. takie jak: _UID, _GID, _SYSTEMD_SLICE, _PID, _COMM, _EXE, _CMDLINE, _SYSTEMD_CGROUP, _SYSTEMD_UNIT. Można użyć tych pól do zapytań np:


# journalctl _COMM=sshd
# journalctl _PID=567
# journalctl _TRANSPORT=kernel
# journalctl _SYSTEMD_UNIT=sshd.service

Zapytanie o log danego unitu:


# journalctl -u name.type

Log z ostatniego bootowania:


# journalctl -b [0]

Log z poprzedniego bootowania


# journalctl -b -1

TIP1: Przekazywanie logu na 12‑sty wirtualny terminal:


# cat <<EOF > /etc/systemd/journald.conf.d/fw-tty12.conf
[Journal]
ForwardToConsole=yes
TTYPath=/dev/tty12
MaxLevelConsole=info
EOF

TIP2: Jak dobrać się do logów z zamontowanego dysku zewnętrznego?:


# journalctl -D /mnt/var/log/journal -xe

TIP3: Domyślnie polecenie journalctl obcina zbyt długie linie. Można to zmienić: Domyślne parametry pagera "less" to FRSXMK, pomiń "S", aby linie były wyświetlane w całości, np:


# SYSTEMD_LESS=FRXMK journalctl

lub ustaw zmienną środowiskową SYSTEMD_LESS na stałe w /etc/profile[.d] lub ~/.bash_profile:


# export SYSTEMD_LESS=FRXMK

Czas

Serwer czasu, czyli usługa odpowiedzialna za synchronizację czasu na naszym serwerze to teraz "chrony", a nie jak kiedyś "ntp". Zainstaluj "chrony" i uaktualnij plik konfiguracyjny, np: dodając wpisy do pliku:


# grep "^server " /etc/chrony.conf 
server 0.pl.pool.ntp.org iburst
server 1.pl.pool.ntp.org iburst
server 2.pl.pool.ntp.org iburst
server 3.pl.pool.ntp.org iburst

Następnie możemy uruchomić usługę chrony:


# systemctl enable chronyd
# systemctl start  chronyd

Weryfikacja poprawności działania usługi chrony:


# chronyc sources -v

Teraz możemy sprawdzić naszą konfigurację systemd:


 # timedatectl [status]
      Local time: wto 2015-11-10 15:16:37 CET
  Universal time: wto 2015-11-10 14:16:37 UTC
        RTC time: wto 2015-11-10 14:16:37
       Time zone: Europe/Warsaw (CET, +0100)
 Network time on: yes
NTP synchronized: yes
 RTC in local TZ: no

Plik strefy czasowej jest tu:


# file /etc/localtime
/etc/localtime: symbolic link to /usr/share/zoneinfo/Europe/Warsaw

Ustaw strefę:


# timedatectl list-timezones
# timedatectl set-timezone Europe/Warsaw

Ustaw czas "ręcznie":


# timedatectl set-time 9:00:00

Włącz/wyłącz synchronizację z NTP:


# timedatectl set-ntp {true|false|0|1|on|off}

Domyślnie Real Time Clock jest ustawiony na UTC ("yes"), ale możesz go przestawić na "localtime" ("no"). Nie wiem, po co, bo wszystkie serwery czasu działają wg UTC.


# timedatectl set-local-rtc {true|false|0|1|on|off}

Locale - personalizacja

Pliki konfiguracyjne:


/etc/locale.conf
/etc/vconsole.conf
/etc/X11/xorg.conf.d/00-keyboard.conf

Rozpoznanie:


# localectl status
   System Locale: LANG=pl_PL.utf8
       VC Keymap: pl2
      X11 Layout: pl
       X11 Model: pc105
     X11 Options: terminate:ctrl_alt_bksp

# localectl list-locales | grep -i pl
pl_PL
pl_PL.iso88592
pl_PL.utf8

Ustawienie polskich "lokali":


# localectl set-locale LANG=pl_PL.utf8

Zmiana ustawień klawiatury "systemowej" (nie X11!!!):


# localectl list-keymaps | grep -i pl
# localectl set-keymap pl2

Jeśli jednak chcesz koniecznie ustawić inny układ dla X11 (uwaga: polecenie automatycznie konwertuje i zmienia układ klawiatury systemowej):


# localectl set-x11-keymap pl

Bez konwertowania (tylko X11):


# localectl --no-convert set-x11-keymap pl

Uwaga: Z tego wniosek iż prościej najpierw zmienić ustawienia klawiatury dla X11, potem systemowej.

Hostname

Wg Red Hat: "hostname" to maksymalnie 64 znakowy ciąg znaków. Red Hat rekomenduje aby "hostname" był formatu FQDN (fully-qualified domain name), czyli np: host.example.com, czyli taki, jaki używany jest w usłudze DNS.

Dalsze rekomendacje to: - tylko małe litery (7 bit ASCII) - bez spacji i kropek - użycie "_" też może być problematyczne, szczególnie przy starszych systemach

Polecenie "hostnamectl" ograniczy Cię do: "a‑z", "A‑Z", "0‑9", “‑”, “_”, “.”, a kropka nie może występować na końcu, początku lub obok siebie.


# hostnamectl [status]

Chcesz zmienić "hostname"?:


# hostnamectl set-hostname host.example.com

lub


# echo host.example.com > /etc/hostname
# systemctl restart systemd-hostnamed

Pliki tymczasowe

man tmpfiles.d

Systemd posiada podsystem odpowiedzialny za utrzymywanie plików, linków symbolicznych i katalogów tymczasowych.

systemd-tmpfiles-setup

Systemd podczas startu uruchamia usługę "systemd-tmpfiles-setup", która uruchamia polecenie:


/usr/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev

Opcje:

  • --create - tworzy brakujące pliki, katalogi, linki
  • --remove - usuwa przeznaczone do usunięcia pliki, katalogi, linki
  • --boot - wykonuje operację przeznaczone do wykonania tylko podczas uruchamiania systemu
  • --clean - wykonuje "czyszczenie" plików i katalogów
  • --exclude-prefix=/dev - pomija wszelkie pliki urządzeń

Polecenie to zaczytuje konfigurację z:

  • /usr/lib/tmpfiles.d/*.conf - dostarczone przez pakiet (nie zmieniać!!!)
  • /etc/tmpfiles.d/*conf - tam umieszczamy naszą twórczość

Pliki, katalogi i linki zaznaczone do usunięcia, zostają usunięte. Pliki, katalogi i linki zaznaczone do utworzenia zostają stworzone (z niezbędną korektą uprawnień).

systemd-tmpfiles-clean

System może działać długo, więc dodatkowo skonfigurowany jest "timer" systemd-tmpfiles-clean.timer:


[Timer]
OnBootSec=15min
OnUnitActivateSec=1d

Timer ten 15 minut po uruchomieniu systemu (i następnie raz na dobę) uruchomi usługę o tej samej nazwie: systemd-tmpfiles-clean.service, a usługa ta uruchomi polecenie:


# systemd-tmpfiles --clean

Uwaga:  Jak wiadomo mamy czasy: mtime (data modification), ctime (change status) i atime (access). Plik/katalog uznaje się za "przestarzały" jeśli WSZYSTKIE te czasy spełniają tej warunek.

Pliki konfiguracyjne składają się z 6 kolum: "type path mode uid gid age argument"

Type - rodzaje operacji:

  • d - stwórz katalog, jeśli go nie ma
  • D - stwórz lub wyczyść katalog
  • f - stwórz plik
  • F - stwórz plik lub go wyczyść
  • L - stwórz symlink jeśli nie istnieje

Przykłady:


 d /run/systemd/seats 0755 root root -
 D /home/student 0700 student student 1d
 L /run/fstablink - root root - /etc/fstab
 L+ /etc/mtab - - - - ../proc/self/mounts
 # Unlink the X11 lock files
 r! /tmp/.X[0-9]*-lock

Opcja z '!' - można uruchomić tylko przy starcie systemu (-‑boot). Bez wykrzyknika uważa się, żę można bezpiecznie wykonywać zadanie kiedykolwiek. Znak "+" oznacza, że jeśli plik/katalog/link istnieje, to zostanie zastąpiony nowym. (uwaga: link potrafi zastąpić plik lub katalog)

Możesz stworzyć własny plik konfiguracyjny i przetestować go poleceniami ("czyszczenie", "tworzenie" lub "usuwanie" plików/katalogów)


# systemd-tmpfiles --clean  /etc/tmpfiles.d/your_file.conf
# systemd-tmpfiles --create /etc/tmpfiles.d/your_file.conf
# systemd-tmpfiles --remove /etc/tmpfiles.d/your_file.conf

Oczywiście, po zmianie konfiguracji należy powiadomić o tym systemd:


 # systemctl daemon-reload
 # systemctl restart systemd-tmpfiles-clean

D-Bus / kdbus

Tu jest dokładny opis, jak działają obie szyny.

D‑bus - mechanizm (szyna) pozwalający na komunikację między procesami (inter-process communication (IPC)) i zdalne wywoływanie procedur (remote procedure call (RPC)) Systemd nie jest już zależny od biblioteki "libdbus". Cała komunikacja z szyną ma miejsce poprzez nową bibliotekę: sd‑bus. Kiedy obsługa kdbus jest włączona (domyślnie jeszcze nie jest - może w 2016 roku) wtedy proces PID=1 konfiguruje szynę systemową i włącza obsługę unitów typu "busname", które mają za zadanie enkapsuować odwołania do kdbus.

Cel jest prosty: - zastąpić d‑bus nową szyną: kdbus - szyna ta ma działać na "wczesnym" etapie uruchamiania systemu

Wylistowanie wszystkich ("unique names" i "well-known names") szyn:


# busctl

Wylistowanie tylko "unikalnych":


 # busctl list --unique

Wylistowanie tylko dobrze znanych


 # busctl list --acquired

Wylistowanie wszystkich usług w postaci drzewa:


# busctl tree
(...)
Service org.freedesktop.PolicyKit1:
L¦/org
  L¦/org/freedesktop
    L¦/org/freedesktop/PolicyKit1
      L¦/org/freedesktop/PolicyKit1/Authority

Service org.fedoraproject.FirewallD1:
L¦/org
  L¦/org/fedoraproject
    L¦/org/fedoraproject/FirewallD1
      L¦/org/fedoraproject/FirewallD1/config
        +¦/org/fedoraproject/FirewallD1/config/icmptype
        - +¦/org/fedoraproject/FirewallD1/config/icmptype/0
(...)

Wylistowanie jednej usługi:


 # busctl tree org.freedesktop.login1
L¦/org/freedesktop/login1
  +¦/org/freedesktop/login1/seat
  - +¦/org/freedesktop/login1/seat/seat0
  - L¦/org/freedesktop/login1/seat/self
  +¦/org/freedesktop/login1/session
  - +¦/org/freedesktop/login1/session/c1
  - L¦/org/freedesktop/login1/session/self
  L¦/org/freedesktop/login1/user
    +¦/org/freedesktop/login1/user/_1000
    L¦/org/freedesktop/login1/user/self

Konkretnie o konkretnej usłudze:


# busctl introspect org.freedesktop.login1 /org/freedesktop/login1/user/_1000
NAME                                TYPE      SIGNATURE RESULT/VALUE                             FLAGS
org.freedesktop.DBus.Introspectable interface -         -                                        -
.Introspect                         method    -         s                                        -
org.freedesktop.DBus.Peer           interface -         -                                        -
.GetMachineId                       method    -         s                                        -
.Ping                               method    -         -                                        -
org.freedesktop.DBus.Properties     interface -         -                                        -
.Get                                method    ss        v                                        -
.GetAll                             method    s         a{sv}                                    -
.Set                                method    ssv       -                                        -
.PropertiesChanged                  signal    sa{sv}as  -                                        -
org.freedesktop.login1.User         interface -         -                                        -
.Kill                               method    i         -                                        -
.Terminate                          method    -         -                                        -
.Display                            property  (so)      "c1" "/org/freedesktop/login1/session... emits-change
.GID                                property  u         1000                                     const
.IdleHint                           property  b         false                                    emits-change
.IdleSinceHint                      property  t         0                                        emits-change
.IdleSinceHintMonotonic             property  t         0                                        emits-change
.Linger                             property  b         false                                    -
.Name                               property  s         "mb"                                     const
.RuntimePath                        property  s         "/run/user/1000"                         const
.Service                            property  s         "user@1000.service"                      const
.Sessions                           property  a(so)     1 "c1" "/org/freedesktop/login1/sessi... emits-change
.Slice                              property  s         "user-1000.slice"                        const
.State                              property  s         "active"                                 -
.Timestamp                          property  t         1438083988241975                         const
.TimestampMonotonic                 property  t         24245141                                 const
.UID                                property  u         1000                                     const

Pobranie wartości dowolnego parametru:


# busctl get-property org.freedesktop.login1 /org/freedesktop/login1/user/_1000   org.freedesktop.login1.User Sessions
a(so) 1 "c1" "/org/freedesktop/login1/session/c1"

kdbus

Na ten moment kdbus nie jest domyślną szyną systemową, ale możesz wymusić jej użycie dodając w programie ładującym (GRUB) parametr "kdbus=1". Zmodyfikuj w pliku /etc/default/grub zmienną GRUB_CMDLINE_LINUX_DEFAULT dodając "kdbus=1", a następnie uaktualnij konfigurację GRUB poleceniem:


(Arch Linux)# grub-mkconfig -o /boot/grub/grub.cfg

Po restarcie sprawdź, czy opcja ta faktycznie miała zastosowanie:


 # cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-4.2.0-0.rc5.git3.1.fc24.x86_64 (...) kdbus=1

Upewniamy się, czy mamy (automatycznie) zamontowany specjalny system plików:


# mount | grep kdbus
kdbusfs on /sys/fs/kdbus type kdbusfs (rw,nosuid,nodev,noexec,relatime)

 # ls -al /sys/fs/kdbus/
total 0
dr-xr-xr-x. 2 root root 0 Aug 11 09:21 .
drwxr-xr-x. 8 root root 0 Aug 11 09:21 ..
dr-xr-xr-x. 2 root root 0 Aug 11 09:21 0-system
dr-x------. 2 root root 0 Aug 11 09:25 0-user
-rw-rw-rw-. 1 root root 0 Aug 11 09:21 control

 # ls -al /sys/fs/kdbus/0-system/
total 0
dr-xr-xr-x. 2 root root 0 Aug 11 09:21 .
dr-xr-xr-x. 2 root root 0 Aug 11 09:21 ..
-rw-rw-rw-. 1 root root 0 Aug 11 09:21 bus

 # ls -al /sys/fs/kdbus/0-user/
total 0
dr-x------. 2 root root 0 Aug 11 09:25 .
dr-xr-xr-x. 2 root root 0 Aug 11 09:21 ..
-rw-------. 1 root root 0 Aug 11 09:25 bus

Uwaga: Jeśli kolumna DESCRIPTION (wynik polecenia "busctl") jest niepusta, to używasz kdbus!!! Dodatkowo prawidłowe załadowanie modułu 'kdbus' dodatkowo można zweryfikować potwierdzając istnienie katalogu: /sys/fs/kdbus/0-system

Podsumowanie

Jak widać mówienie o systemd jak o menadżerze usług to "małe" niedomówienie... W następnej części kontenery "nspawn" i zarządzanie siecią "networkd".

Wybrane dla Ciebie
Komentarze (7)