SSHセッションで実行されているプログラムの出力をすぐに停止します。

SSHセッションで実行されているプログラムの出力をすぐに停止します。

質問

SSH経由で大量の情報を出力するコマンドを実行します。たとえば、100万回実行したり、ただcat /dev/urandom楽しく実行したループにデバッグ情報を愚かに追加しました。

端末はメッセージでいっぱいです。

私が言う内容の例を見てください。

できるだけ早くコマンドを終了し、プログラムを修正したいと思います。私はそれが何を印刷しても構いません。さて、問題はCtrl+ ASAPを押しますC(上記の例ではコマンドを実行した直後に押されました)。不要なすべての情報を印刷するにはまだ時間がかかります。

私が試したこと

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

CtrlS明らかに読んだ端末に「出力停止、追いつく必要があります」と知らせるために使用されます。しかし、明らかにそれは何もしません。

その他の詳細

私は私が実行したプログラムがこのように終わることができることを覚えていませんが、どのような状況でも自分自身を保存できるように、私が実行するコマンドを変更したくありません。

私の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できるように出力を実行します。lessq

$ 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リモート側に送信すると、実行中のプログラムが中断されます。プログラムが存在し、シェルはプロンプトを再表示するために文字を送信します。プロンプトが表示される前に最初にバッファリングされ、送信されたすべてのデータが画面に表示されます。

あなたが求めるのは、プログラムが停止し、転送中のデータが何とか消えることです。すでに進行中なので、こういうことは起こりません。

このデータが表示されないようにする唯一の方法は、端末をシャットダウンしてリモートデバイスに再接続することです。ただし、これはバッファリングされたデータが表示されるのを待つよりも大変です。

答え3

バッファリングにはいくつかのレベルがあります。Ctrl+を押すと、Cプログラムは端末へのデータ転送を停止します。これは、端末エミュレータにまだ表示されていないデータには影響しません。

非常に速い速度でデータを表示すると、端末が追いつかず、遅延が発生します。これがまさにここで起こるものです。テキストの表示は、これらの乱数を生成するよりもはるかに高価です。はい、ビットマップフォントを使用しても暗号化品質乱数を生成するのは比較的安価です。 (私のコンピュータでこれを試してみましたが、XプロセスはCPUをxterm数%に飽和させ、catかろうじて1%に達しました(乱数生成で考慮)。これはビットマップフォントを使用するときです)

今すぐ停止するには、端末エミュレータを終了します。これを望まない場合は、少なくともウィンドウを最小化してください。 xtermなどのスマート端末エミュレータはウィンドウをマップしないため、X CPU時間が節約されるため、ガベージマークがより早く完了します。 Xサーバーは優先順位が高いため、xtermがバックグラウンドでデータを処理している間、これはコンピュータの応答性に大きな影響を与えます。

これらすべてがリモートシェルで実行されると、生成されたデータがcat最初にSSH接続を受ける必要があるため、待ち時間がさらに悪化します。Ctrl+を押してSSH経由で接続する必要がありますC。優先順位は高くなりますが(帯域外送信)、まだ時間がかかり、その間に多くの出力が蓄積されます。 SSH接続を閉じること(Enter次へを押すことで実行できます)以外に、~.転送中のデータを抑制する方法はありません。

答え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は期待どおりに動作し、バッファリングされたコンテンツがほとんどないため、すぐに出力を終了します。

関連情報