Dlaczego SSH nie czeka na procesy w tle?

13

Dlaczego ssh -tnie czeka na zakończenie zadań w tle?

Przykład:

ssh user@example 'sleep 2 &'

Działa to zgodnie z oczekiwaniami, ponieważ ssh powraca po 2 sekundach, podczas gdy

ssh user@example -t 'sleep 2 &'

nie czeka na sleepzakończenie i natychmiast wraca.

Czy ktoś może wyjaśnić przyczynę tego? Czy istnieje sposób, aby ssh -tpoczekać na zakończenie wszystkich procesów w tle przed powrotem?

Mój przypadek użycia polega na tym, że uruchamiam skrypt ssh -t, a ten skrypt uruchamia kilka zadań w tle, które powinny pozostać przy życiu po zakończeniu głównego skryptu. Z ssh -ttym nie jest do tej pory możliwe.

Philipp Murry
źródło

Odpowiedzi:

22

Bez -t, sshdpobiera standardowe wyjście zdalnej powłoki (i dzieci podobne sleep) i stderr przez dwie potoki (a także wysyła dane wejściowe klienta przez inną potok).

sshd czeka na proces, w którym uruchomił powłokę logowania użytkownika, ale także po zakończeniu tego procesu czeka na eof na standardowej rurze (przynajmniej nie na rurce stderr w przypadku co najmniej openssh).

A eof dzieje się, gdy żaden proces nie otwiera deskryptora pliku na końcu zapisu potoku, co zwykle dzieje się tylko wtedy, gdy wszystkie procesy, które nie zostały przekierowane na standardowe wyjście, znikną.

Kiedy używasz -t, sshdnie używa rur. Zamiast tego cała interakcja (stdin, stdout, stderr) ze zdalną powłoką i jej dziećmi odbywa się za pomocą jednej pary pseudo-terminali.

W przypadku pary pseudo-terminali do sshdinterakcji ze stroną master nie ma podobnej obsługi eof ani żadnego sposobu, aby dowiedzieć się, czy nadal istnieją procesy z fds otwartym na stronę slave pseudo-terminala, więc po prostu czeka na zakończenie proces, w którym wykonał powłokę logowania zdalnego użytkownika, a następnie kończy działanie.

Po tym wyjściu strona główna pary pty jest zamykana, co oznacza, że ​​pty jest niszczona, więc procesy kontrolowane przez slave otrzymają SIGHUP (który domyślnie by je zakończył).

Stéphane Chazelas
źródło
1
dzięki za dokładną odpowiedź! jeszcze jedno, co chciałbym wiedzieć: czy wszystkie procesy w tle kończą się po wyjściu z pseudo terminala? skrypt, który zaczynam, uruchamia usługę, która działa dobrze z ssh. ale przy użyciu ssh -t usługa nie jest uruchomiona. wygląda na to, że usługa zostaje zamknięta po powrocie ssh.
Philipp Murry
Właściwie istnieje sposób, aby strona główna pseudo-terminala wiedziała, kiedy wszystkie deskryptory plików podrzędnych zostały zamknięte. Jest to ten sam mechanizm uruchamiany przez prawdziwy terminal, gdy wszystkie deskryptory plików zostały w rzeczywistości zamknięte.
JdeBP
@JdeBP, chciałbyś się rozwinąć? Nie jestem pewny co masz na myśli. Emulatory terminalu AFAICT (przynajmniej xterm i terminal gnome) nie przejmują się procesami, w których fds wciąż są otwarte dla slave'a, gdy proces, w którym wykonali powłokę, umiera
Stéphane Chazelas
@PhilippMurry Możesz użyć, nohupaby skrypt działał w ten sposób. (Możesz również rozważyć uruchomienie długotrwałych zadań wewnątrz, tmuxaby móc interaktywnie monitorować ich postępy, ale plik dziennika działa dobrze.)
jpaugh
5

Użyj wait:

ssh user@example -t 'sleep 2 & wait'
Ipor Sircer
źródło