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


18

问题

我执行通过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客户端CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin在MinTTY中的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)上运行。


您在哪个系统上运行产生输出的实际程序?Linux,Unix或Windows?Linux和UNIX应该接受Ctrl-O,这意味着“丢弃写入此终端的所有输出”。
Mark Plotnick 2014年

服务器在Debian上运行。编辑了问题。Ctrl-O似乎也无能为力。也许这是客户的事?
rr-

您可以尝试使用该-j选项启动xterm ,以启用跳转滚动。基本问题是,远程设备发送数据的速度比终端窗口显示数据的速度快-默认情况下,每次打印新行时,它都必须对窗口的内容进行位控制。到远程系统接收Ctrl-C时,大量数据可以被缓冲,并且终端程序将尝试显示所有数据。
Mark Plotnick 2014年

只是一个想法:如果您有一些通常不经意地执行的确切命令,并且它们会产生大量输出,为什么不只是在其中附加一些别名.bashrc呢?
psimon 2014年

您可以使用mosh而不是ssh:mosh.mit.edu
gmatht

Answers:


5

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

您要的是使程序停止并且正在传输的数据以某种方式消失。那不可能发生,因为它已经在途中。

确保看不到这些数据的唯一方法是退出终端,然后重新连接到远程设备-但这比等待缓冲的数据显示要花费更多的精力。


10

我通常将输出运行到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的文章:标准流中的缓冲。它甚至包括漂亮的图片。

参考文献


只要您记得附加|lesscmd,那是合理的,不幸的是我经常不这样做。如果您运行了该程序cmd,则仍然需要等到它完成后,再打印接收到的计算结果^C
rr-

1
那并不能真正解释发生了什么。毕竟,不涉及管道,所以您指的是什么缓冲区?
吉尔斯(Gillles)“所以-不再是邪恶的”

@Gilles-抱歉,缓冲区将是屏幕的缓冲区。
slm

什么缓冲区?在内核中?在xterm中?
吉尔斯(Gilles)'所以

@吉尔斯-给我一点时间,我在寻找细节8
slm

3

有几种缓冲级别。当您按Ctrl+时C,这将阻止程序向终端发送数据。这不会影响终端仿真器尚未显示的数据。

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

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

当所有这些都在远程Shell中进行时,滞后会更加严重,因为产生的数据cat必须首先通过SSH连接。您按Ctrl+ C也必须通过SSH连接;它获得了更高的优先级(已带外发送),但是仍然需要一些时间来积累更多的输出。除非关闭SSH连接(您可以通过按Enterthen来完成~.),否则无法抑制传输中的数据。


问题与SSH有关。STDOUT缓冲区不应在交互模式下使用,但SSH无法正确处理交互模式。尽管事务中可能挂起许多输出,但是SSH进程接收Ctrl + C,因此当无法将Ctrl + C传递到远程时,杀死输出是他的责任。
user4674453

@ user4674453嗯?Ctrl + C不应杀死本地输出。这根本不是它的工作。它应该传递给远程端,这可能会杀死远程进程,也可能不会杀死它。
吉尔斯(Gillles)“所以-别再邪恶了”

“它应该传递给远程端,这可能会也可能不会杀死远程进程。” -也不应这样做。Ctrl + C发出其中之一的KILL信号仅用于本地过程。如果未将其用于本地过程,则“假定为”的概念根本不适用。
user4674453

@ user4674453号Ctrl + C不是终止信号。这是一个中断信号。它的作用是返回交互式提示。它只会杀死没有交互式提示返回的程序。
吉尔斯(Gilles)“所以,别再邪恶了”

“这是一个中断信号。” 它是kill命令的参数,因此是kill信号。如果愿意,有时将其称为POSIX信号。“它的作用是返回交互式提示。它只会杀死没有交互式提示返回的程序。” 究竟!!!而且SSH并没有达到预期的效果。
user4674453

1

找到一条通往命令的途径就足够killcat
对于以下建议,您可能需要打开第二个ssh连接。

  • 很少CTRL+z有比这样更有效的CTRL+c:它可以更快地回答。之后,您可以中止该命令,可以使用kill %1或任何它的作业号将其杀死。
    希望您仍然能够从屏幕上读取任何内容(大量的随机二进制文本很容易弄乱您的字符集)。
    Gilles所记住的,如果最小化窗口,则系统读取中断请求的速度可能比杀死进程要快。因此,暂停/中断,最小化,稍等一下,再次最大化,也可以是一个解决方案。
    当然,通过ssh连接,我希望您需要等待一些时间。

  • 在另一个终端/会话中,您可以询问pgrep cat(是否调用了cat命令),并确定cat进程正在使用更多的CPU。您可以使用以下命令更精确地识别它pstree

    pgrep猫| awk'{print“ pstree -sp” $ 1}“ | sh | grep sshd

    用类似的输出回答

    init(1)───sshd(1062)───sshd(22884)───sshd(22951)───bash(22957)───cat(23131)

    在这种情况下,您只需要杀死Cat PID:kill 23131

注意:


1

我遇到了同样的问题,对此处的答案不满意,因此我进行了更深入的研究。其他人已经提到,您的命令输出数据的速度比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

如果您的连接速度不时下降,您可能需要稍微降低RATE。如果下降,则该行为将恢复为无响应ctrl-c。

可选的节流猫别名:

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

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

# usage: tcat <FILENAME>

现在ctrl-c可以按预期工作,因为几乎没有缓冲,所以立即终止了输出。


cat与其他软件不同,输出很少成为问题。作者仅以它为例。问题通常是由于其他软件所致,如果它愿意产生大量输出,则可能并不明显。使用任何类型的前缀或后缀命令都不是解决方案,因为键入它会花费一些时间。结果将不会有任何收益。
user4674453

0

Linux上有一个软件可以完全解决问题(还有其他几件事)。您也可以从Windows中的终端仿真器调用它(您似乎正在使用Windows?)。

尝试使用mosh,它是SSH二进制文件的替代品。它的工作原理与SSH完全一样(您可以mosh user@hostname代替SSH ,ssh user@hostname并且可以完全按预期运行,甚至可以进行私钥身份验证等。

它基本上在服务器上运行一个单独的进程来缓冲数据包。因此,当您在mosh上按Ctrl + C时,它将把它传送到远程服务器,然后远程服务器将停止发送额外的信息。此外,它还能预测击键的结果,每按一次键可以节省几毫秒。

缺点:目前,使用mosh时无法向上滚动历史记录。

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.