关闭连接后,如何远程终止称为“ tail -f”的终端?


24

我只是注意到,如果执行ssh user@remote_host tail -f /some/filetail -f /some/file即使ssh连接已关闭,它也会继续在remote_host上运行!

因此,经过几次连接和断开连接后,运行次数会tail -f /some/file增加。tail -fssh连接关闭时如何实际终止?

Answers:


33

ssh host tail -f file

ssh客户端连接到sshd服务器上host通过TCP连接。sshd运行tail -f,其标准输出重定向到管道。sshd读取来自管道另一端的内容,并将其封装在sshd协议中以发送给ssh客户端。(使用rshdtailstdout可以直接sshd用作套接字,但是可以添加加密,并且能够在单个TCP连接上多路复用多个流(例如,用于端口/代理/ X11 /隧道重定向,stderr),因此必须诉诸管道。)

当您按CTRL-C时,SIGINT发送到ssh客户端。那导致ssh死亡。死后,TCP连接关闭。因此,上hostsshd模具也是如此。tail不会被杀死,但是它的标准输出现在是另一端没有读取器的管道。因此,下次它向标准输出中写入内容时,它将收到SIGPIPE并死亡。

在:

ssh -t host 'tail -f file'

和是一样的,只是sshd和之间的通信不是通过管道,tail而是通过伪终端进行。tail的stdout是从属伪终端(如/dev/pts/12),并且在主端进行的任何tail写操作read(可能由tty行规程修改)都由客户端sshd发送并封装到ssh客户端。

在客户端,使用-tssh将终端置于raw模式。特别是,这将禁用终端规范模式和终端信号处理。

所以,当你按下Ctrl+C,而不是客户端的终端线路规范发送SIGINT的ssh工作,这仅仅发送^C通过连接字符sshdsshd写道,^C远程终端的主端。远程终端的线路规则发送SIGINTtailtail然后死亡,sshd退出并关闭连接并ssh终止(如果它仍然不忙于端口转发或其他操作)。

同样,使用-t,如果ssh客户端死亡(例如,如果输入~.),则连接将关闭并sshd死亡。结果,SIGHUP将发送到tail

现在,请注意使用-t具有副作用。例如,使用默认的终端设置,\n字符将转换为,\r\n并且取决于远程系统,可能会发生更多的事情,因此,stty -opost如果该输出不打算用于远程主机,则可能要在远程主机上发出(以禁用输出后处理)终端:

$ 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

使用-t/的另一个缺点-tt是stdout和stderr在客户端上没有区别。远程命令的stdout和stderr都将被写入ssh客户端的stdout:

$ 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,如果ssh客户端死亡(例如,如果输入~.),”又是什么~.
x-yuri

1
@ x-yuri ~.是您输入的用于断开客户端连接的转义序列。有关man ssh详细信息,请参见。
斯蒂芬·查泽拉斯

11

您需要在远程端分配终端:

ssh -t user@remote_host tail -f /some/file

甚至

ssh -tt user@remote_host tail -f /some/file

1
谢谢,无论是-t还是-tt作品。但是我仍然无法理解其真正原因:例如,当我远程调用shell并关闭连接时,shell终止了。但是tail -f不是。当然,我已经在中阅读了有关-toption的信息man ssh,但并没有太大帮助。似乎我不理解某些泛型,如果您建议一些文档阅读它,或者自己解释一下,我将很高兴。谢谢!
德米特里·弗兰克

2
@DmitryFrank我的理解是:如果连接断开,则sshd发送SIGHUP。但是如果没有终端,就不会有终端连接挂断……
Hauke Laging

谢谢,我将阅读SIGHUP和其他信号,但对此一无所知。
德米特里·弗兰克

fyi:我只是尝试运行tail -f,然后打开htop并发SIGHUP送给它(按F9-> 1-> Enter),然后tail -f终止!所以,原因应该有一些不同..
梅德弗兰克

3
@DmitryFrank您误解了问题。问题在于它tail不会做出反应SIGHUP。问题在于,如果没有伪终端,SIGHUP**不会发送给tail。通过在两种情况下都附加strace,您可以看到这一点tail
Hauke Laging
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.