Dlaczego „proces nie może rozwidlać” dla usług typu prostego w systemd?

Aug 15 2020

Chcę napisać własne systemdpliki jednostek, aby zarządzać naprawdę długo działającymi poleceniami 1 (w kolejności godzin). Przeglądając artykuł ArchWiki na systemd , mówi się o wyborze typu uruchomienia:

Type=simple(domyślnie): systemd uważa, że ​​usługa jest uruchamiana natychmiast. Proces nie może się rozwidlać . Nie używaj tego typu, jeśli inne usługi muszą być zamówione w tej usłudze, chyba że jest ona aktywowana przez gniazdo.

Dlaczego proces w ogóle nie może się rozwidlać? Czy to odnosi się do rozwidlenia w stylu procesu przywoływania demona (rodzic rozwidla, a następnie wychodzi), czy jakiegokolwiek rodzaju rozwidlenia?


1 Nie chcę tmux / screen, ponieważ chcę bardziej eleganckiego sposobu sprawdzania stanu i ponownego uruchamiania usługi bez uciekania się do tmux send-keys.

Odpowiedzi

41 Gilles'SO-stopbeingevil' Aug 15 2020 at 17:29

Usługa może wywołać wywołanie forksystemowe. Systemd nie zapobiegnie temu, a nawet nie zauważy, jeśli tak jest. To zdanie odnosi się konkretnie do praktyki rozwidlania na początku demona w celu odizolowania demona od jego procesu nadrzędnego. „Proces nie może forkować [i wychodzić z elementu nadrzędnego podczas uruchamiania usługi w procesie podrzędnym]”.

Strona podręcznika wyjaśnia to bardziej --long i ze sformułowaniami, które nie prowadzi do tego szczególnego zamieszania.

Wiele programów, które mają być używane jako demony, ma tryb (często tryb domyślny), w którym po uruchomieniu izolują się od swoich rodziców. Demon uruchamia się, wywołuje fork(), a rodzic kończy pracę. Proces potomny wywołuje, setsid()więc działa we własnej grupie procesów i sesji, a także uruchamia usługę. Celem jest to, że jeśli demon jest wywoływany z wiersza poleceń powłoki, demon nie otrzyma żadnego sygnału z jądra ani z powłoki, nawet jeśli coś stanie się z terminalem, na przykład zamknięcie terminala (w takim przypadku powłoka wysyła SIGHUP do wszystkich znanych mu grup procesów). Powoduje to również, że proces obsługi jest zaadoptowany przez init, który zbierze go po wyjściu, unikając zombie, jeśli demon został uruchomiony przez coś, co by tego nie wait()zrobiło (nie miałoby to miejsca, gdyby demon został uruchomiony przez powłokę ).

Gdy demon jest uruchamiany przez proces monitorowania, taki jak systemd, rozwidnianie przynosi efekt przeciwny do zamierzonego. Proces monitorowania ma ponownie uruchomić usługę, jeśli ulegnie awarii, więc musi wiedzieć, czy usługa zostanie zamknięta, a to jest trudne, jeśli usługa nie jest bezpośrednim elementem podrzędnym procesu monitorowania. Proces monitorowania nigdy nie umrze i nie ma terminala sterującego, więc nie ma obaw o niepożądane sygnały lub żniwa. Dlatego nie ma powodu, aby proces serwisowy nie był elementem podrzędnym monitora i jest dobry powód, aby tak było.

15 JdeBP Aug 16 2020 at 11:59

Zignoruj ​​tę stronę wiki Arch.

Ma rzeczy całkiem nie tak, jeśli chodzi o Typeustawienie. Co więcej, nie ogranicza się to tylko do jego opisów simple. To, o czym mówi forking, też jest złe.

Właściwe zalecenia dla tego rodzaju rzeczy istnieją od dziesięcioleci dłużej niż sam systemd i sięgają co najmniej do wczesnych lat dziewięćdziesiątych. Jak zauważyłem whttps://unix.stackexchange.com/a/476608/5132, w doco systemd znajduje się wersja Johnny-come-later zaleceń dla demonów, która w dużej mierze powtarza to, co użytkownicy demonów, IBM, ludzie używają inittabi… cóż… powtarzam od dziesięcioleci. (To była już często udzielana odpowiedź, kiedy pisałem ją jako taką w 2001 roku).

Powtarzać:

Jeśli twój program ma jakiś mechanizm "demonizacji", który w szczególności forkuje dziecko i wychodzi z procesu rodzica, wyłącz go i nie używaj . Dzięki daemontools et al. tam, gdzie było to wymagane przez długi czas, wiele programów rozwinęło zdolność do nie posiadania takich mechanizmów w ciągu ostatnich 20 lat, a inne po prostu nie domyślnie „demonizują” w pierwszej kolejności, więc mogą być używane w ich domyślne tryby pracy.

Podsystemy zarządzania usługami już uruchamiają procesy usługowe w kontekście demona . Te procesy nie muszą „demonizować”. (Rzeczywiście, w wielu współczesnych systemach operacyjnych błędem jest myślenie, że programy mogą nawet „demonizować” z kontekstu sesji logowania, i właśnie o to chodzi w „demonizacji”.) Mają już wartości środowiska i deskryptory otwartych plików, odpowiednie do kontekstu demona, a kilka rzeczy wykonywanych przez „demonizację” w rzeczywistości udaremnia niektóre konwencjonalne czynności, które są regularnie wykonywane z demonami (np. przechwytywanie ich standardowych wyników / błędów w dzienniku) przez menedżerów usług.

Preferuj Type=simple, z wczesnym otwieraniem gniazda (gdzie zarządzanie usługą otwiera gniazda serwera i przekazuje je jako już otwarte deskryptory plików do programu usługi) lub Type=notify.

  • Type=simple traktuje usługę jako gotową (aby usługi zamówione na niej mogły być uruchamiane / zatrzymywane) zaraz po rozpoczęciu procesu usługi, z wczesnym otwieraniem gniazda z wykorzystaniem semantyki połączenia gniazda w celu opóźnienia klientów usługi w punktach, w których próbują połączyć się z serwerami usługi, dopóki serwery nie będą faktycznie gotowe.
  • Type=notifyma tę wadę, że jest charakterystyczny dla systemd i dla Linuksa (obok problemów związanych z brakiem funkcjonalności w przypadku krótkotrwałych procesów, takich jak tworzenie powłoki systemd-notify, oraz stosowania parsowania formularzy czytelnych dla człowieka do formularzy czytelnych maszynowo w procesie uprzywilejowanym, gdzie problemy z parserem zdarzały się już w przeszłości), ale ma tę zaletę, że zapewnia lepszą kontrolę (z punktu widzenia programu usługi), kiedy usługa jest faktycznie uważana za gotową. Umożliwia także pewne dostosowanie wyjścia stanu.

Programy usługowe obu typów mogą się rozwidlać. Problem stanowi rozwidlenie, a następnie wyjście z pierwotnego procesu .

(Należy zauważyć, że jest to taki sam problem w przypadku uruchamiania programów z powłok, jak w przypadku uruchamiania programów od menedżerów usług, gdzie użytkownicy widzą, że programy kończą się i powodują niemal natychmiastowe wyświetlenie kolejnego monitu powłoki. Rzeczywiście, właśnie dzisiaj ktoś pytał, jeszcze raz , o uruchamianiu programów z powłoki, która rozwidla i kończy rodzica, w Dlaczego czasami, gdy uruchamiam program w terminalu, nie działa on w terminalu? )

Type=oneshotprawdopodobnie nie jest tym, czego potrzebujesz w tym konkretnym przypadku, ponieważ usługa jest uważana za gotową tylko wtedy, gdy cały program serwisowy został ukończony. Ma swoje zastosowania, ale sądząc po dźwiękach, one cię nie dotyczą.

Nigdy nie używaj Type=forking. Powinno to być ostateczność desperacji, ponieważ prawie żaden program nie mówi protokołu . Robią coś innego , co w rzeczywistości nie jest tym protokołem, nie współpracuje poprawnie z tym protokołem, a tak naprawdę nie sygnalizuje gotowości.

Dalsza lektura

  • Jonathan de Boyne Pollard (2001). Błędy, których należy unikać podczas projektowania uniksowych programów demonów . Często udzielane odpowiedzi.
  • Jonathan de Boyne Pollard (2015). Naprawdę nie musisz demonyizować. Naprawdę. . Systemowy Dom Grozy.
  • Jonathan de Boyne Pollard (2015). Problemy z protokołem gotowości z demonami uniksowymi . Często udzielane odpowiedzi.
  • https://unix.stackexchange.com/a/401611/5132