Dlaczego „su -c <polecenie> &” najwyraźniej pozwala na uruchomienie polecenia w tle bez rozłączania się

11

Pomagałem koledze, który miał problemy z procesem w tle umierającym okresowo.

Dowiedziałem się, że zaczynają proces w tle, logując się na serwerze i wykonując:

su - <user> -c '<command>' &

„Aha”, wykrzyknąłem. „Jeśli uruchomisz polecenie za pomocą„ & ”, zawiesi się ono po wyjściu ze sterującego terminalu. Aby to osiągnąć, musisz użyć czegoś takiego jak nohup. Naprawdę ten proces musi obsługiwać działanie jako demon, tut tut.”

Przetestowaliśmy powyższe polecenie, aby wykazać mój punkt widzenia i ... wydawało się, że działa: proces rozpoczęty przez polecenie nie zakończył się, gdy opuściliśmy terminal, który uruchomił powyższe polecenie.

polecenie to niestandardowy skrypt Pythona, którego dane wyjściowe trafiają do pliku. O ile mogę stwierdzić, w skrypcie nie ma inteligentnych możliwości „demonizacji”. Nie wykonuje żadnych czynności potrzebnych do działania jako demon wymieniony na stronie Wikipedia: Daemon (computing): Creation .

Uruchomienie polecenia w ten sposób zachowuje się zgodnie z oczekiwaniami:

<command> &
exit

W powyższym przypadku proces w tle rozpoczęty przez polecenie kończy się, gdy wychodzimy z terminala.

Moje pytanie brzmi:

  1. Co się dzieje, gdy dodamy „su - -c &”, który uniemożliwia zakończenie procesu po wyjściu naszego terminalu. Chciałbym szczegółowo zrozumieć w odniesieniu do terminala sterującego, standardowego wejścia i wyjścia itp.

  2. Czy jest to rozsądny sposób na osiągnięcie celu uruchomienia tego polecenia jako procesu w tle. Jeśli nie to dlaczego?

Chcę promować najlepsze praktyki w mojej firmie, ale muszę być w stanie zademonstrować i poprzeć wszelkie rekomendacje, które przedstawię.

Chcę również zrozumieć, co się dokładnie dzieje.

Sam Elstob
źródło

Odpowiedzi:

12

Istnieje kilka sposobów na zabicie procesu z powodu umierającego terminalu.

  1. Pierwszy sposób polega na tym, że sterownik terminala w jądrze wysyła sygnał SIGHUP do procesu sterującego, dla którego terminal jest terminalem sterującym . W większości przypadków procesem kontrolnym jest powłoka, która jest początkowo uruchamiana w terminalu, a jego terminal kontrolny to ten, do którego podłączone są jego stdin, stdout i stderr. Proces zostanie rozłączony z terminalem sterującym, jeśli zadzwoni setsid.

  2. Drugi sposób polega na tym, że powłoka, gdy otrzymuje SIGHUP, ponownie wysyła ten sygnał do swoich podprocesów, a dokładniej do zadań w tle. Niektóre powłoki (ksh, bash, zsh) mają disownwbudowane polecenie mówiące powłoce, aby nie wysyłała ZATRZYMANIA do określonego zadania.

  3. Jeśli terminal zniknie, a program spróbuje go odczytać, zostanie powiadomiony o stanie końca pliku (lub ewentualnie EIO dla zadania w tle). Jeśli terminal zniknie, a program spróbuje do niego zapisać, zapis powróci z błędem EIO. Może to spowodować zamknięcie programu.

Zatem suzmiany tutaj polegają na tym, że (2) normalnie powoduje, że początkowa powłoka zabija zadanie w tle, ale ponieważ proces w tle działa jako inny użytkownik, sygnał nie może zostać dostarczony, a proces w tle trwa.

Gilles „SO- przestań być zły”
źródło
Widziałem, jak robi to użytkownik root chroot --userspec root:root / sh -c "exec some_forever_process" &. Zadanie działa jako ten sam użytkownik, bez wyraźnego nohupwcześniejszego lub disownpóźniejszego. Więc w takim przypadku, w jaki sposób sygnał nie może zostać dostarczony przy terminie wyjścia?
Toddius Zho
@ToddiusZho Przypuszczalnie some_forever_processmiał działać wiecznie (demon), więc chroni się przed otrzymaniem SIGHUP z wyjścia terminala (działając we własnej grupie procesów).
Gilles „SO- przestań być zły”
bash / tail nie chroni przed SIGHUP, ale to wciąż działa: `` local $ ssh root @ REMOTE_HOST remote # chroot --userspec root: root / sh -c "exec bash -c 'tail -f / dev / null '”I [1] 6376 zdalne # ps -p $! --no-header -o pid, uid, polecenie -ww 6376 0 tail -f / dev / null remote # exit local $ ssh root @ REMOTE_HOST remote # ps -p 6376 --no-head -o pid, uid, polecenie -ww 6376 0 tail -f / dev / null ``
Toddius Zho