立即停止在 SSH 会话中运行的程序的输出

立即停止在 SSH 会话中运行的程序的输出

问题

我执行通过 SSH 输出大量信息的命令。例如,我愚蠢地在执行一百万次的循环中添加调试信息,或者只是cat /dev/urandom为了好玩而运行。

终端里充斥着信息。

举例说明我正在谈论的内容

我想尽快终止命令并修复我的程序。我不在乎它打印什么。现在,问题是我按下了Ctrl+ CASAP(在上面的示例中,我在运行命令后立即按下了它),但是打印所有我不需要的信息仍然需要时间

我尝试过的

我尝试按Ctrl+C如此用力,以至于当终端最终赶上时,它产生了有趣的结果:

OUTPUT HERE^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
^C^C

^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C

我还读到了Ctrl+S显然用于告诉终端“停止输出,我需要赶上”但显然它什么也没做。

杂项细节

我不想改变我运行的命令,这样我就可以在任何情况下拯救自己,即使我不记得我运行的程序可能会这样结束。

我的 SSH 客户端在 MinTTY 中的 Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) 上运行,终端类型设置为xterm-256color

SSH 服务器在 Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux) 上运行。

答案1

我通常将输出运行到,less以便我可以通过less使用q密钥来杀死它。

$ cmd | less

例子

$ cat /dev/urandom | less

   SS #2

点击q+后Enter,它将退出并返回到正常终端,使其保持干净整洁。

为什么会发生这种情况?

您遇到的问题是有一些缓冲区(用于 STDOUT)与显示器的输出一起排队。这些缓冲区被填满的速度如此之快,以至于您无法足够快地中断它以停止它。

                                    SS #1

要禁用/限制此效果,您可以禁用 STDOUT 缓冲,这应该使用 使事情变得更加敏感stdbuf,但您可能必须使用这些设置才能按照您想要的方式获得事情。要取消缓冲 STDOUT,您可以使用以下命令:

$ stdbuf -o0 <cmd>

手册页stdbuf详细介绍了您可以使用的选项:

    If MODE is 'L' the corresponding stream will be line buffered.  This 
    option is invalid with standard input.

    If MODE is '0' the corresponding stream will be unbuffered.

    Otherwise MODE is a number which may be followed by one of the 
    following: KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so
    on for G, T, P, E, Z, Y.  In this case the corresponding stream will be 
    fully buffered with the  buffer  size  set  to  MODE
    bytes.

要了解缓冲如何工作的良好背景,我强烈建议您查看这篇 Pixel Beat 的文章,标题为:标准流中的缓冲。它甚至包括漂亮的图片。

参考

答案2

其中一些输出将被缓冲。您将Ctrl+发送C到远程端,这会中断正在运行的程序。该程序存在,并且 shell 发送字符以再次向您显示提示符。在显示提示之前,您的屏幕将首先显示所有已缓冲且已发送给您的数据。

您要求的是程序停止并且传输中的数据以某种方式消失。这是不可能发生的,因为它已经在路上了。

确保看不到此数据的唯一方法是退出终端,然后重新连接到遥控器 - 但这可能比等待缓冲数据显示要费力得多。

答案3

有多个级别的缓冲。当您按Ctrl+时C,程序将停止向终端发送数据。这不会影响终端模拟器尚未显示的数据。

当您以非常高的速度显示数据时,终端无法跟上并且会出现滞后。这就是这里发生的事情:显示文本比生成这些随机数要昂贵得多。是的,即使使用位图字体 - 相比之下,生成加密质量的随机数也非常便宜。 (我刚刚在我的机器上尝试过,X 进程使 CPU 饱和,xterm占用了几个 %,cat(随机数生成所考虑的)勉强达到 1%。而且这是使用位图字体时的情况。)

如果您希望现在停止,请终止终端模拟器。如果您不想这样做,至少最小化窗口;智能终端仿真器(例如xterm)不会映射窗口,这节省了X CPU时间,因此垃圾会更快地完成显示。 X 服务器具有高优先级,因此当 xterm 在后台处理数据时,这将对计算机的响应能力产生很大影响。

当这一切都在远程 shell 中进行时,延迟会更严重,因为产生的数据cat必须首先通过 SSH 连接。你按Ctrl+C也必须通过 SSH 连接;它获得了更高的优先级(它被发送到带外),但这仍然需要一些时间,在此期间积累更多的输出。除了关闭 SSH 连接(可以通过按Enterthen 来完成~.)之外,无法抑制传输中的数据。

答案4

我遇到了同样的问题,并且对这里的答案不满意,因此我进行了更深入的研究。其他人已经提到你的命令输出数据的速度比你的 ssh 可以接受的速度快,因此数据缓冲区和缓冲区无法停止。

要解决此问题,请通过将命令输出限制为 ssh 会话可以采用的最大速率来避免缓冲,已经存在可以执行此操作的命令。

设置时,首先找出您的会话最大速率:

# Get transfer <TIME> of a large file (>10MB preferable)
/usr/bin/time -f "%e" cat <FILENAME>

# Get file <SIZE> in bytes
stat --printf="%s\n" <FILENAME>

# Calculate <RATE>
echo "<SIZE> / <TIME>" | bc

最后,相应地限制你的实际命令。

<YOUR_COMMAND> | pv -qL <RATE>

例子:

/usr/bin/time -f "%e" cat large_reference_file.txt
31.26

stat --printf="%s\n" cat large_reference_file.txt
17302734

echo "17302734 / 31.26" | bc
553510

# Throttle my command to 553510B/s
cat some_other_file.txt | pv -qL 553510

您可能需要稍微降低速率,以防您的连接速度不时下降一点。如果它下降,行为将返回问题,即无响应的 ctrl-c。

可选的节流猫别名:

# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'

# tcsh
alias tcat 'cat \!* | pv -qL 400k'

# usage: tcat <FILENAME>

现在 ctrl-c 按预期工作,立即终止输出,因为缓冲的内容很少(如果有的话)。

相关内容