Systemd i proces spawnowania


14

Nie zamieszczaj tutaj normalnie, ale odrywam włosy od tego. Mam skrypt w języku Python, który uruchamia się podczas uruchamiania i jest odpowiedzialny za uruchomienie szeregu innych procesów. Ten skrypt był uruchamiany przy starcie przez sysvinit, ale ostatnio uaktualniłem do Debian Jessie, więc dostosowałem go do uruchamiania przez systemd.

Niestety mam problem, którego nie mogę rozwiązać. Po uruchomieniu skryptu bezpośrednio w powłoce użytkownika uruchamia on poprawnie procesy potomne, a gdy skrypt się kończy, procesy potomne są osierocone i kontynuują działanie.

Po uruchomieniu przez systemd, jeśli proces nadrzędny kończy działanie, wszystkie dzieci również wychodzą (cóż, ekran, który uruchamiają w die i pojawiają się jako Dead ???)

Idealnie powinienem móc zrestartować skrypt nadrzędny bez zabijania wszystkich procesów potomnych, czy jest coś, czego mi brakuje?

Dzięki!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Edycja: Prawdopodobnie warto wskazać, że skrypt Pythona jest zasadniczo „kontrolerem” procesów potomnych. Uruchamia i zatrzymuje serwery na ekranach GNU zgodnie z żądaniem serwera centralnego. Zwykle zawsze działa, nie odradza usług i nie wychodzi. Są jednak przypadki, w których chciałbym móc ponownie załadować skrypt bez zabijania procesów potomnych, nawet jeśli oznacza to, że procesy są osierocone do pid 1. W rzeczywistości nie ma znaczenia, czy skrypt Pythona uruchamia procesy jako proces nadrzędny, jeśli jest to w ogóle możliwe.

Lepsze wyjaśnienie, jak to działa:

  • Systemd spawn /Server.py
  • Server.py rozwidla i zapisuje plik pid dla Systemd
  • Server.py następnie spawnuje procesy serwera na ekranie GNU zgodnie z jego instrukcjami
  • Server.py nadal działa, aby wykonać wszelkie restarty wymagane od serwera

Podczas uruchamiania bez Systemd Server.py można zrestartować, a uruchomione przez niego ekrany GNU pozostają nienaruszone. Podczas uruchamiania za pomocą Systemd, gdy Server.py zamyka się, zamiast procesów ekranowych osieroconych do pid 1, zostają zabici.


1
Trudno jest znaleźć rozwiązanie bez Server.pykodu i opisu, jak rozwidlają się uruchomione usługi (jeśli rozwidlają). Jednak ogólnie rzecz biorąc, jest to problem niedopasowania protokołu gotowości .
intelfx

BTW, ExecStop=to nie jest potrzebne. Domyślną akcją systemd przy zatrzymaniu jest zabicie procesów. Możesz zajrzeć do dokumentacji KillMode=dyrektywy.
intelfx

1
I w końcu ... Jeśli nie ma odpowiedniego protokołu gotowości (jednego simplelub forkingfaktycznie), ostatecznością byłoby Type=oneshot, RemainAfterExit=yesi KillMode=control-group.
intelfx

@intelfx Zasadniczo skrypt Pythona uruchamia serwer na ekranie za pomocą Subprocess.call. Jest to o wiele bardziej skomplikowane, ponieważ skrypt otrzymuje polecenia z innego miejsca, informujące o tym, które ekrany uruchomić, a które nie. Dostępne ekrany są również dynamiczne, dlatego też nie mogą być usługami systemowymi. Idealnie nie chcę, aby systemd traktował te ekrany jako część usługi, ale obecnie są one zrzucane w tej samej grupie procesów i giną wraz z masterem, jeśli zostanie zrestartowany.
Bottswana

Mam przeczucie, że systemd nie „obsługuje” takiego procesu kontrolnego (po prostu wyszukuje PID w czasie startu, nie rozpoznaje późniejszych ...): |
rogerdpack,

Odpowiedzi:


9

Udało mi się to naprawić, ustawiając KillMode do przetwarzania zamiast grupy kontrolnej (domyślnie). Dziękuje wszystkim


Wydaje się, że jest to coś więcej niż poprawka, zobacz inne odpowiedzi ... jeśli to zrobisz i wykonasz „systemctl stop”, to nie zabije procesów potomnych, które nadal będą działać [?] poza nadzorem systemctl?
rogerdpack

5

Mam skrypt w języku Python, który uruchamia się podczas uruchamiania i jest odpowiedzialny za uruchomienie szeregu innych procesów.

Co wskazuje, że robisz to źle. Więcej w tym za chwilę.

po wyjściu skryptu procesy potomne są osierocone i kontynuują działanie.

To nie jest poprawne zachowanie demona. Jeśli „główny” proces - w tym przypadku dziecko, które rozwidliłeś, ponieważ tak określiłeś Type=forking- kończy działanie, systemd uważa, że ​​usługa została dezaktywowana i kończy wszelkie inne nadal działające procesy (w grupie kontrolnej) w celu uporządkowania .

Czasami konwersja rcskryptów System 5 na systemd nie jest prosta, ponieważ właściwy sposób wykonywania zadań w systemied jest zupełnie inny. Właściwy sposób wykonania (powiedzmy) OpenVPN, OpenStack lub OSSEC HIDS w systemd nie jest taki sam, jak w przypadku rcskryptu. Fakt, że masz skrypt, który rozwidla, a następnie odradza całą masę procesów wnuków, a następnie wychodzi z oczekiwania, że ​​te wnuki będą nadal działać, oznacza, że ​​popełniacie ten sam rodzaj horroru ossec-control, jakkolwiek, chociaż z dwoma mniejszymi poziomami rozwidlania. Jeśli zauważysz, że piszesz skrypt „główny”, który sprawdza flagi „włącz” i uruchamia procesy potomne dla „włączonych” części twojego systemu, to popełniasz ten sam błąd co horrendous ossec-control.

Z systemd nie są potrzebne takie domowe mechanizmy. Jest już menedżerem serwisu. Według /unix//a/200365/5132 właściwym sposobem na obejście tego w systemd nie jest posiadanie jednej usługi, która rodzi jakąś zwariowaną i mylącą próbę posiadania „pod-usług”. Ma to mieć każdy proces potomny jako pełnoprawną usystematyzowaną usługę. Następnie włącza się i wyłącza oraz uruchamia i zatrzymuje różne części systemu za pomocą zwykłych kontrolek systemd. Jak widać w przypadku OSSEC HIDS, prosty szablon usługi obejmuje prawie wszystkie usługi (jeden wyjątek znajduje się na stronie /ubuntu//a/624871/43344 ), umożliwiając wykonywanie takich czynności, jak systemctl enable ossec@agentlessd.servicewłączenie opcjonalnegoagentlessdusługi, bez jakiejkolwiek potrzeby strasznego mechanizmu „skryptu głównego”, który był potrzebny w Systemie 5 rc.

Istnieje wiele przypadków, może nie tak ekstremalnych jak OSSEC HIDS, w których takie przemyślenie jest konieczne. MTS, takie jak exim i sendmail, to dwa takie. Ktoś mógł mieć jeden rcskrypt, który uruchamia moduł uruchamiający kolejkę, serwer wysyłania SMTP i serwer przekaźnika SMTP, z kilkoma zmiennymi powłoki ad hoc w pliku konfiguracyjnym, aby kontrolować dokładnie, które są uruchamiane. Ale właściwym sposobem na zrobienie tego w systemie systemd jest posiadanie trzech odpowiednich jednostek usług (z których dwie mają powiązane jednostki gniazd ) i brak ad hoc, tylko zwykłe mechanizmy menedżera usług.


Doceniam opinie na ten temat. Chociaż zgadzam się, że korzystanie z usług podzestawów ma sens, zostało to zrobione w Pythonie z powodu, do którego nie mogę wejść. Moim jedynym rozwiązaniem jest znalezienie sposobu, aby ta metoda działała. W każdym razie dzięki. Chciałbym to zrobić poprawnie.
Bottswana

Usługi podrzędne uruchamiane przez skrypt to tylko serwery działające na ekranie GNU jako określony użytkownik. Serwery te bardzo się zmieniają, niektóre są dodawane, niektóre są usuwane, a to jest kontrolowane gdzie indziej, więc nie mogą tak naprawdę być rzeczywistymi usługami w systemie, ponieważ zwiększa to złożoność i nie można nimi zarządzać centralnie. Ten sam skrypt jest również używany na serwerach niesystemowych.
Bottswana

systemd ma wyraźne funkcje umożliwiające dodawanie i usuwanie usług bez potrzeby dostępu do konta root. „Używany również w usługach niesystemowych” to jedyny z powyższych argumentów, których nie można naprawić dodając więcej systemd… cóż, prawdopodobnie nawet to samo może być. :)
Charles Duffy

0

Możesz po prostu uśpić rodzica i poczekać, aż systemd zabije go w chwili zatrzymania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.