Usługa Systemd Unit uruchomi się ponownie, jeśli uruchomi się lub ponownie załaduje inna usługa

16

Chciałbym wiedzieć, czy istnieje sposób Systemdna restart A.service( After) po B.serviceuruchomieniu lub przeładowaniu (tylko przeładuj konfigurację), jeśli to możliwe bez edycji, B.servicektóra jest instalowana i aktualizowana przez system.

A.servicepowinien rozpocząć się, nawet jeśli B.servicenie jest zainstalowany, wyłączony lub zatrzymany.

A.service:

[Unit]
After = B.service network-online.target
Wants = B.service

[Service]
Type=oneshot
ExecStart = /script.sh start
ExecStop = /script.sh stop
RemainAfterExit=yes

[Install]
WantedBy = network-online.target

B.service:

[Unit]
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/cmd start
ExecStop=/cmd stop
ExecReload=/cmd reload
PIDFile=/var/run/cmd.pid

[Install]
WantedBy=multi-user.target
Alex
źródło

Odpowiedzi:

12

Możesz użyć PartOfw [Unit]sekcji.

Przykład: PartOf=B.service

Ze strony podręcznika

PartOf =

Konfiguruje zależności podobne do Wymaga =, ale ogranicza się do zatrzymywania i restartowania jednostek. Gdy systemd zatrzyma lub uruchomi ponownie wymienione tutaj jednostki, akcja jest propagowana do tej jednostki. Zauważ, że jest to zależność jednokierunkowa - zmiany w tej jednostce nie wpływają na wymienione jednostki.

Thushi
źródło
Dzięki, patrzyłem na Overriding vendor settingsto, ale wygląda to na jeszcze łatwiejsze i bardziej obiecujące, tylko excpetion jest, że nie chcę Aprzestać, jeśli Bprzestanę, tylko A.restartjeśli B.start, w każdym razie wkrótce zrobię jakiś test i zobaczę, czy jest jakiś sposób, aby sobie z tym poradzić, to poinformuje cię
Alex
@Alex: Co jeśli używasz PartOfi Restart=alwaysrazem?
Thushi,
Patrzę na Restart=dokumentację, nie jestem pewien, jakie jest zachowanie z oneshotusługami, ale niezależnie:: When the death of the process is a result of systemd operation (e.g. service stop or restart), the service will not be restartedjeśli dobrze rozumiem, ręczne zatrzymanie B zatrzymałoby A
Alex
Cóż, teraz nagroda automatycznie przypisuje się do wygaśnięcia, @Thushi Doceniam twój wysiłek i sugestię, ale PartOfnie jest to rozwiązanie na pytanie, i tak ciesz się.
Alex
@Alex: Cóż, punkty nie są dla mnie ważne. Jest tyle innych sposobów na zdobywanie punktów. Chcę tylko wiedzieć, czy dostarczone rozwiązanie rozwiązuje problem. Jeśli nie, będziemy dalej nad tym pracować. Co powiesz na korzystanie PartOfz Restart=always? Próbowałeś tego?
Thushi,
3

Nie miałem kontrolę nad stopz PartOf=, i Anie musi zatrzymać się B, więc skończyło się za pomocą nadrzędnych ustawień dostawcy , wydaje się działać.

/etc/systemd/system/B.service.d/override.conf

[Service]
ExecStart=
ExecStart=/bin/sh -c '/cmd start || exit $?; sleep 5; [ -x /script.sh ] && /script.sh start; exit 0'
ExecReload=
ExecReload=/bin/sh -c '/cmd reload || exit $?; sleep 5; [ -x /script.sh ] && /script.sh start; exit 0'

/cmdimplementacja jest asynchroniczna i dostęp do zasobu, który również /script.shwymaga dostępu, nie znalazłem nic lepszego (na razie) spać kilka sekund.

Próbowałem użyć systemctl [--no-block] try-restartprzed użyciem /script.shbezpośrednio, ale nie działało.

Alex
źródło
Szukam również rozwiązania dla tego scenariusza. Czy mógłbyś bardziej wyjaśnić to rozwiązanie? lub podaj link do niektórych dokumentów, aby przeczytać i zrozumieć, co zrobiłeś.
zappy
Cześć @zappy, poszukaj instrukcji man systemd.unit(lub przeszukaj ją online, jeśli nie jest zainstalowany) i poszukaj rozdziału „Zastępowanie ustawień dostawcy”.
Alex
Dziękuję za Twój wkład. Rozumiem, że wybrałeś powyższą metodę tylko dlatego, że usługa B jest specyficzna dla dostawcy i nie chcesz edytować tego pliku usługi. Ale w moim przypadku zarówno usługi A, jak i B nie są dostarczane przez dostawcę. Wydaje mi się, że zastąpienie go może zwiększyć złożoność systemu. Czy mamy jakieś inne opcje?
zappy
Pytanie ma kilka lat, czy sprawdziłeś dokumentację? Być może od tego czasu omówiono ten scenariusz. W tym czasie się spieszyłem, ale mając czas, szukałem systemowej oficjalnej listy mailingowej i pytałem, w końcu otwieram problem
Alex
1

W tej chwili systemd nie obejmuje tego senario. Nie można osiągnąć tej funkcji za pomocą samych plików serwisowych. Jedną z możliwości jest przejęcie kontroli systemctl za pomocą skryptu powłoki o tej samej nazwie, a następnie sprawdzenie, czy B.service ma zostać ponownie uruchomione lub ponownie załadowane, wykonaj odpowiednie działania również z A.service, aw razie potrzeby zaktualizuj rc.local, aby również przejść do odpowiedniego stanu podczas rozruchu. Mam ten problem z docker.service i networking.service, ale po prostu zawsze je ponownie uruchamiam:

systemctl uruchom ponownie docker.service networking.service

Oczywiście nie byłoby to skuteczne, gdyby systemd sam zmanipulował B.service wewnętrznie (np. Za pośrednictwem innych plików serwisowych).

kaveh minooie
źródło