Jak zastąpić lub skonfigurować usługi systemowe?

109

Wiele skryptów inicjujących sysv używało odpowiedniego pliku, /etc/defaultaby administrator mógł go skonfigurować. Zadania upstart można modyfikować za pomocą .overrideplików. Jak zastąpić lub skonfigurować jednostki systemowe, skoro systemd jest domyślny w Ubuntu?

muru
źródło
Pamiętaj, że podczas czyszczenia ExecStart=pustego wpisu nie można wstawić następującego komentarza: ExecStart= # Empty line to clear previous entries.To będzie traktowane jako kolejny ExecStart=wpis i dodawane do listy. PS. Nie mogłem dodać komentarza do odpowiedzi Muru z powodu mojej niskiej reputacji.
tysik

Odpowiedzi:

185

systemdjednostki nie muszą słuchać plików w /etc/default. systemdjest łatwo konfigurowalny, ale wymaga znajomości składni plików jednostek systemowych.

Pakiety wysyłają pliki jednostek zwykle w /lib/systemd/system/. Są to nie ma być edytowany. Zamiast tego systemdpozwala zastąpić te pliki, tworząc odpowiednie pliki w /etc/systemd/system/.

Dla danej usługi foopakiet zapewniłby /lib/systemd/system/foo.service. Możesz sprawdzić jego status za pomocą systemctl status foolub przejrzeć jego logi za pomocą journalctl -u foo. Aby zastąpić coś w definicji foo, wykonaj:

sudo systemctl edit foo

Spowoduje to utworzenie katalogu o /etc/systemd/systemnazwie po jednostce i override.confpliku w tym katalogu ( /etc/systemd/system/foo.service.d/override.conf). Możesz dodać lub zastąpić ustawienia, używając tego pliku (lub innych .confplików w /etc/systemd/system/foo.service.d/).

Przesłanianie argumentów poleceń

Weźmy gettyna przykład usługę. Powiedz, że chcę mieć autologin TTY2 dla mojego użytkownika (nie jest to wskazane, ale tylko przykład). TTY2 jest uruchamiany przez getty@tty2usługę ( tty2będącą instancją szablonu /lib/systemd/system/getty@service). Aby to zrobić, muszę zmodyfikować getty@tty2usługę.

$ systemctl cat getty@tty2
# /lib/systemd/system/[email protected]
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by [email protected], not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=

[Install]
WantedBy=getty.target
DefaultInstance=tty1

W szczególności muszę zmienić ExecStartlinię, która obecnie jest:

$ systemctl cat getty@tty2 | grep Exec     
ExecStart=-/sbin/agetty --noclear %I $TERM

Aby to zmienić, wykonaj:

sudo systemctl edit getty@tty2

I dodaj:

[Service]
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

Uwaga:

  1. Musiałem wyraźnie jasne ExecStartprzed ustawieniem go ponownie, jak to, że jest to ustawienie dodatek, podobnie After, Environment(jako całość, a nie per-zmienna) i EnvironmentFile, w przeciwieństwie do nadrzędnych i jak ustawienia RestartSeclub Type. ExecStartmoże mieć wiele wpisów tylko dla Type=oneshotusług.
  2. Musiałem użyć odpowiedniego nagłówka sekcji. W oryginalnym pliku ExecStartznajduje się w [Service]sekcji, więc moje zastąpienie musi również umieścić ExecStartw [Service]sekcji. Często po przejrzeniu rzeczywistego pliku usługi systemctl catdowiesz się, co należy zastąpić i w której sekcji się znajduje.

Zwykle jeśli edytujesz plik jednostki systemowej, aby zadziałał, musisz uruchomić:

sudo systemctl daemon-reload

Jednak systemctl editautomatycznie robi to za Ciebie.

Teraz:

$ systemctl cat getty@tty2 | grep Exec
ExecStart=-/sbin/agetty --noclear %I $TERM
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

$ systemctl show getty@tty2 | grep ExecS
ExecStart={ path=/sbin/agetty ; argv[]=/sbin/agetty -a muru --noclear %I $TERM ; ... }

A jeśli to zrobię:

sudo systemctl restart getty@tty2

i naciśnij CtrlAltF2, presto! Będę zalogowany na moim koncie na tym TTY.

Jak powiedziałem wcześniej, getty@tty2jest to instancja szablonu. Co jeśli chciałbym zastąpić wszystkie wystąpienia tego szablonu? Można to zrobić, edytując sam szablon (usuwając identyfikator instancji - w tym przypadku tty2):

systemctl edit getty@

Przesłanianie środowiska

Częstym przypadkiem użycia /etc/defaultplików jest ustawienie zmiennych środowiskowych. Zwykle /etc/defaultjest skryptem powłoki, więc można w nim używać konstrukcji języka powłoki. W przypadku systemdjednak tak nie jest. Możesz określić zmienne środowiskowe na dwa sposoby:

Przez plik

Załóżmy, że ustawiłeś zmienne środowiskowe w pliku:

$ cat /path/to/some/file
FOO=bar

Następnie możesz dodać do zastąpienia:

[Service]
EnvironmentFile=/path/to/some/file

W szczególności, jeśli /etc/default/grubzawiera tylko przypisania i brak składni powłoki, możesz użyć go jako EnvironmentFile.

Poprzez Environmentwpisy

Powyższe można również osiągnąć za pomocą następującego zastąpienia:

[Service]
Environment=FOO=bar

Jednak może to być trudne w przypadku wielu zmiennych, spacji itp. Spójrz na jedną z moich innych odpowiedzi na przykład takiego wystąpienia.

Dalsza lektura

Dzięki temu mechanizmowi bardzo łatwo jest zastąpić systemdjednostki, a także cofnąć takie zmiany (po prostu usuwając plik zastępowania). To nie jedyne ustawienia, które można modyfikować.

Przydałyby się następujące linki:

muru
źródło
1
Musisz wyczyścić zmienną przed ustawieniem jej dla usług innych niż typu oneshot. To rozwiązało mój problem.
Colin
3
@ MarkEdington ze strony systemd.service(5)podręcznika, sekcja na temat ExecStart: „O ile Type = to oneshot, należy podać dokładnie jedno polecenie. Gdy użyto Type = oneshot, można podać zero lub więcej poleceń. Polecenia można określić, podając wiele wierszy poleceń w tym samym dyrektywa lub alternatywnie ta dyrektywa może być określona więcej niż jeden raz z tym samym skutkiem. Jeśli pusty ciąg zostanie przypisany do tej opcji, lista poleceń do uruchomienia zostanie zresetowana, wcześniejsze przypisania tej opcji nie będą miały wpływu. ”
muru
1
@Orient możesz sudo rmzastąpić plik, a następnie systemctl daemon-reloadlub możesz systemctl editi zastąpić wszystko w zastąpieniu komentarzami. Komentarze w plikach serwisowych zaczynają się od #.
muru
3
@Orientsystemctl revert foo
Ayell
1
Jaki jest porządek pierwszeństwa dla trzech metod (plik zastępowania, plik środowiskowy, zmienna środowiskowa)? To znaczy, dla zmiennej zdefiniowanej we wszystkich trzech, która wartość będzie skuteczna?
Nikolaos Kakouros