Me acabo de dar cuenta de que si ejecuto ssh [email protected]_host tail -f /some/file
, luego tail -f /some/file
sigue ejecutándose en el host_remoto incluso si la conexión ssh está cerrada.
Entonces, después de varias conexiones y desconexiones, la cantidad de tail -f /some/file
en ejecución crece Cómo terminar realmente tail -f
cuando la conexión ssh está cerrada?
Respuesta aceptada:
En
ssh host tail -f file
El ssh
el cliente se conecta al sshd
servidor en host
a través de una conexión TCP. sshd
ejecuta tail -f
con su salida estándar redirigida a una tubería. sshd
lee lo que viene del otro extremo de la tubería y lo encapsula en el protocolo sshd para enviarlo a ssh
cliente. (con rshd
, tail
stdout habría sido el socket directamente, pero sshd
agrega cifrado y es capaz de multiplexar varios flujos (como puerto/agente/X11/redireccionamiento de túnel, stderr) en una sola conexión TCP, por lo que tiene que recurrir a canalizaciones).
Cuando presiona CTRL-C, se envía un SIGINT al ssh
cliente. Eso hace que ssh
morir. Al morir, la conexión TCP se cierra. Y por lo tanto, en host
, sshd
muere también. tail
no se elimina, pero su salida estándar ahora es una canalización sin lector en el otro extremo. Entonces, la próxima vez que escriba algo en su salida estándar, recibirá un SIGPIPE y morirá.
en:
ssh -t host 'tail -f file'
Es lo mismo excepto que en lugar de estar con una tubería, la comunicación entre sshd
y tail
es a través de un pseudo-terminal. tail
's stdout es un pseudo-terminal esclavo (como /dev/pts/12
) y lo que sea tail
escribir hay read
en el lado maestro (posiblemente modificado por la disciplina de línea tty) por sshd
y enviado encapsulado al ssh
cliente.
En el lado del cliente, con -t
, ssh
pone la terminal en raw
modo. En particular, eso deshabilita el modo canónico del terminal y el manejo de la señal del terminal.
Entonces, cuando presionas Ctrl+C , en lugar de que la disciplina de línea del terminal del cliente envíe un SIGINT al ssh
trabajo, que solo envía el ^C
carácter sobre la conexión a sshd
y sshd
escribe que ^C
al lado maestro del terminal remoto. Y la disciplina de línea del terminal remoto envía un SIGINT
a tail
. tail
luego muere, y sshd
sale y cierra la conexión y ssh
termina (si no está todavía ocupado con reenvíos de puertos u otros).
Además, con -t
, si el ssh
el cliente muere (por ejemplo, si ingresa ~.
), la conexión se cierra y sshd
muere Como resultado, se enviará un SIGHUP a tail
.
Ahora, tenga en cuenta que usar -t
tiene efectos secundarios. Por ejemplo, con la configuración de terminal predeterminada, \n
los caracteres se convierten a \r\n
y pueden suceder más cosas según el sistema remoto, por lo que es posible que desee emitir un stty -opost
(para deshabilitar el posprocesamiento de salida) en el host remoto si esa salida no está destinada a una 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
Otro inconveniente de usar -t
/-tt
es que stdout y stderr no se diferencian en el cliente. Tanto el stdout como el stderr del comando remoto se escribirán en el ssh
salida estándar del cliente:
$ ssh localhost ls /x | wc -l
ls: cannot access /x: No such file or directory
0
$ ssh -t localhost ls /x | wc -l
1