Je viens de remarquer que si j'exécute ssh user@remote_Host tail -f /some/file
, alors tail -f /some/file
continue à courir sur la distance_host même si la connexion SSH est fermée!
Donc, après plusieurs connectes et déconnectes, nombre de fonctionnement tail -f /some/file
grandit. Comment finir réellement tail -f
Lorsque la connexion SSH est fermée?
Dans
ssh Host tail -f file
Le client ssh
se connecte au serveur sshd
sur Host
sur une connexion TCP. sshd
exécute tail -f
avec son stdout redirigé vers un tuyau. sshd
lit ce qui vient de l'autre extrémité du tuyau et l'encapsule dans le protocole SSHD à envoyer au client ssh
. (avec rshd
, tail
stdout aurait été le socket directement, mais sshd
ajoute le cryptage et est capable de multiplexer plusieurs flux (comme pour la redirection de Port/Agent/X11/Tunnel , STDRERR) sur une seule connexion TCP Ainsi doit recourir à des pipes).
Lorsque vous appuyez sur CTRL-C, un SIGINT est envoyé au client ssh
. Cette cause ssh
meurt. Lors de la mort, la connexion TCP est fermée. Et donc, sur Host
, sshd
meurt aussi. tail
n'est pas tué, mais son stdout est maintenant un tuyau sans lecteur à l'autre extrémité. Donc, la prochaine fois qu'il écrit quelque chose à son stdout, il recevra un Sigpipe et mourir.
Dans:
ssh -t Host 'tail -f file'
C'est la même chose, sauf que, au lieu d'être avec un tuyau, la communication entre sshd
et tail
est via un pseudo-terminal. tail
's stdout est un pseudo-terminal esclave (comme /dev/pts/12
) et quoi que ce soit tail
écrivit qu'il y a read
du côté maître (éventuellement modifié par la discipline de la ligne TTY) par sshd
et envoyé encapsulé sur le client ssh
.
Du côté du client, avec -t
, ssh
met le terminal dans le mode raw
. En particulier, cela désactive le mode canonique terminal et la manipulation du signal de terminal.
Donc, quand vous appuyez sur Ctrl+C, au lieu de la discipline de la ligne de terminal du client, envoyant un sigint au travail ssh
, qui envoie simplement le caractère ^C
sur la connexion à sshd
et sshd
écrit ^C
au maître côté du terminal distant. Et la discipline de la ligne de la terminer distante envoie un SIGINT
à tail
. tail
puis meurt, et sshd
sort et ferme la connexion et ssh
se termine (si ce n'est pas toujours occupé avec des transfert de port ou autre).
De plus, avec -t
, si le client ssh
meurt (par exemple, si vous entrez ~.
), la connexion est fermée et sshd
meurt. En conséquence, un soupirup sera envoyé à tail
.
Maintenant, méfiez-vous que l'utilisation de -t
a des effets secondaires. Par exemple, avec les paramètres de terminal par défaut, \n
Les caractères sont convertis en \r\n
et plus de choses peuvent se produire en fonction du système distant, vous pouvez donc vouloir émettre un stty -opost
(pour désactiver le post-traitement de sortie) sur l'hôte distant si cette sortie est Non destiné à un 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
Un autre inconvénient de l'utilisation -t
/-tt
est que stdout et stardr ne sont pas différenciés sur le client. Le stdout et STDERR de la commande distante seront écrits sur le stdout de ssh
:
$ ssh localhost ls /x | wc -l
ls: cannot access /x: No such file or directory
0
$ ssh -t localhost ls /x | wc -l
1
Vous avez besoin d'une allocation de terminal sur le côté distant:
ssh -t user@remote_Host tail -f /some/file
ou même
ssh -tt user@remote_Host tail -f /some/file