Právě jsem si všiml, že když spustím ssh [email protected]_host tail -f /some/file
a poté tail -f /some/file
běží na vzdáleném hostiteli, i když je připojení ssh uzavřeno!
Takže po několika připojeních a odpojeních počet spuštěných tail -f /some/file
roste. Jak vlastně ukončit tail -f
když je připojení ssh uzavřeno?
Přijatá odpověď:
V
ssh host tail -f file
ssh
klient se připojí k sshd
server na host
přes TCP spojení. sshd
spustí tail -f
s jeho stdout přesměrovaným do potrubí. sshd
přečte, co přichází z druhého konce roury, a zapouzdří to do protokolu sshd, aby je poslal do ssh
klienta. (pomocí rshd
, tail
stdout by byl přímo soket, ale sshd
přidává šifrování a je schopen multiplexovat několik streamů (jako pro port/agent/X11/přesměrování tunelu, stderr) na jediné TCP spojení, takže se musí uchýlit k rourám).
Když stisknete CTRL-C, do ssh
se odešle SIGINT klienta. To způsobí ssh
zemřít. Po smrti je TCP spojení uzavřeno. A proto na host
, sshd
umírá také. tail
není zabit, ale jeho stdout je nyní roura bez čtečky na druhém konci. Takže až příště něco napíše do svého stdoutu, dostane SIGPIPE a zemře.
V:
ssh -t host 'tail -f file'
Je to to samé, až na to, že místo toho, aby se jednalo o rouru, komunikace mezi sshd
a tail
je přes pseudoterminál. tail
‘s stdout je podřízený pseudoterminál (jako /dev/pts/12
) a jakýkoli tail
zápis tam je read
na hlavní straně (pravděpodobně upraveno disciplínou tty line) pomocí sshd
a odeslány zapouzdřené do ssh
klient.
Na straně klienta pomocí -t
, ssh
přepne terminál do raw
režimu. Konkrétně to deaktivuje kanonický režim terminálu a zpracování terminálového signálu.
Když tedy stisknete Ctrl+C namísto toho, aby disciplína terminálové linky klienta odeslala SIGINT do ssh
úloha, která pouze odešle ^C
znak přes připojení k sshd
a sshd
zapíše, že ^C
na hlavní stranu vzdáleného terminálu. A linková disciplína vzdáleného terminálu odešle SIGINT
na tail
. tail
pak zemře a sshd
ukončí a uzavře připojení a ssh
se ukončí (pokud není jinak stále zaneprázdněn přesměrováním portů nebo jiným).
Také pomocí -t
, pokud ssh
klient zemře (například pokud zadáte ~.
), spojení je uzavřeno a sshd
zemře. V důsledku toho bude SIGHUP odeslán na tail
.
Nyní pozor, pomocí -t
má vedlejší účinky. Například s výchozím nastavením terminálu \n
znaky jsou převedeny na \r\n
a v závislosti na vzdáleném systému se může stát více věcí, takže možná budete chtít vydat stty -opost
(pro zakázání následného zpracování výstupu) na vzdáleném hostiteli, pokud tento výstup není určen pro terminál:
$ 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
Další nevýhodou použití -t
/-tt
je, že stdout a stderr nejsou na klientovi rozlišeny. Jak stdout, tak stderr vzdáleného příkazu budou zapsány do ssh
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