W
ssh host tail -f file
ssh
Klient łączy się z sshd
serwerem na host
pośrednictwem połączenia TCP. sshd
działa tail -f
z przekierowaniem standardu na potok. sshd
odczytuje to, co pochodzi z drugiego końca potoku i hermetyzuje go w protokole sshd, aby wysłać do ssh
klienta. (z rshd
, tail
stdout byłby bezpośrednio gniazdem, ale sshd
dodaje szyfrowanie i jest w stanie multipleksować kilka strumieni (jak dla przekierowania portu / agenta / X11 / tunelu, stderr) na jednym połączeniu TCP, więc musi uciekać się do potoków).
Po naciśnięciu CTRL-C do ssh
klienta wysyłany jest SIGINT . To powoduje ssh
śmierć. Po śmierci połączenie TCP zostaje zamknięte. A zatem host
, sshd
matryce, jak również. tail
nie jest zabity, ale jego stdout jest teraz rurą bez czytnika na drugim końcu. Tak więc, następnym razem, gdy napisze coś na swoje standardowe wyjście, otrzyma SIGPIPE i umrze.
W:
ssh -t host 'tail -f file'
To to samo, z tą różnicą, że zamiast być z potokiem komunikacja między sshd
i tail
odbywa się za pośrednictwem pseudo-terminala. tail
stdout jest pseudo-terminalem slave (podobnym /dev/pts/12
) i cokolwiek tail
zapisuje read
się po stronie master (być może zmodyfikowane przez dyscyplinę linii tty) sshd
i wysyłane jest do enkapsulacji do ssh
klienta.
Po stronie klienta -t
, ssh
przełącza terminal w raw
tryb. W szczególności wyłącza to tryb kanoniczny terminala i obsługę sygnału terminala.
Tak więc, gdy naciśniesz Ctrl+C, zamiast dyscypliny linii terminalu klienta wysyłającej SIGINT do ssh
zadania, to po prostu wysyła ^C
znak przez połączenie sshd
i sshd
zapisuje go ^C
do strony głównej zdalnego terminala. A dyscyplina liniowa zdalnego terminala wysyła SIGINT
do tail
. tail
następnie umiera, sshd
opuszcza i zamyka połączenie i ssh
przerywa połączenie (jeśli nie jest zajęte przekazywaniem portów lub innymi).
Ponadto, -t
jeśli ssh
klient umrze (na przykład jeśli wejdziesz ~.
), połączenie zostanie zamknięte i sshd
umrze. W rezultacie SIGHUP zostanie wysłany do tail
.
Teraz uważaj, że używanie -t
ma skutki uboczne. Na przykład przy domyślnych ustawieniach terminala \n
znaki są konwertowane na \r\n
i w zależności od systemu zdalnego może się zdarzyć więcej rzeczy, więc możesz chcieć wydać stty -opost
(aby wyłączyć przetwarzanie końcowe danych wyjściowych) na zdalnym hoście, jeśli dane wyjściowe nie są przeznaczone terminal:
$ ssh localhost 'echo x' | hd
00000000 78 0a |x.|
00000002
$ ssh -t localhost 'echo x' | hd
00000000 78 0d 0a |x..|
00000003
$ ssh -t localhost 'stty -opost; echo x' | hd
00000000 78 0a |x.|
00000002
Kolejną wadą używania -t
/ -tt
jest to, że stdout i stderr nie są zróżnicowane na kliencie. Zarówno stdout, jak i stderr polecenia zdalnego zostaną zapisane ssh
na stdout klienta:
$ ssh localhost ls /x | wc -l
ls: cannot access /x: No such file or directory
0
$ ssh -t localhost ls /x | wc -l
1
-t
, jeślissh
klient umrze (na przykład, jeśli wejdziesz~.
)” „Co jest~.
znowu?~.
to sekwencja ucieczki wprowadzana w celu odłączenia klienta. Zobaczman ssh
szczegóły.Potrzebny jest przydział terminali po stronie zdalnej:
lub nawet
źródło
-t
lub-tt
działa. Ale nadal nie rozumiem prawdziwej przyczyny tego: powiedzmy, że kiedy wywołuję powłokę zdalnie i zamykam połączenie, powłoka zostaje zakończona. Aletail -f
nie jest. Oczywiście już czytałem o-t
opcji wman ssh
, ale to niewiele pomogło. Wygląda na to, że nie rozumiem niektórych generyków i byłbym szczęśliwy, gdybyś zasugerował kilka dokumentów do przeczytania na ten temat lub prawdopodobnie sam to wyjaśnił. Dzięki!sshd
wysłany komunikatSIGHUP
. Ale tam, gdzie nie ma terminala, nie może być rozłączenia połączenia terminala ...SIGHUP
i inne sygnały, wciąż nic o tym nie wiem.tail -f
, a następnie otworzyłemhtop
i wysłałemSIGHUP
do niego (naciskającF9
->1
->Enter
) itail -f
zakończyłem! Powód powinien być inny ...tail
że nie zareagowałbySIGHUP
. Problem polega na tym, żeSIGHUP
** nie jest wysyłany dotail
bez pseudo terminala. Możesz to zobaczyć, dołączającstrace
siętail
w obu przypadkach.