web-dev-qa-db-fra.com

Comment terminer à distance appelé "queue -f" lorsque la connexion est fermée?

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?

24
Dmitry Frank

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
33

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
11
Hauke Laging