web-dev-qa-db-ja.com

SSHセッションで実行中のプログラムからの出力を停止する

問題

SSHで大量の情報を出力するコマンドを実行しています。たとえば、何百万回も実行するループの中にデバッグ情報を愚かに追加したり、キックのために_cat /dev/urandom_を実行したりします。

ターミナルは情報であふれています。

Example what I'm talking about

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

私が試したこと

押してみた 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_)で実行されます。

18
rr-

その出力の一部はバッファリングされます。あなたはあなたを送る Ctrl+C 実行中のプログラムを中断するリモートエンド。プログラムが存在し、シェルは文字を送信してプロンプトを再度表示します。プロンプトが表示される前に、画面には最初にバッファリングされたすべてのデータが表示され、すでにそこに送られています。

あなたが求めているのは、プログラムを停止して、転送中のデータがどういうわけか消えることです。それはすでに進行中であるので、それは起こり得ない。

このデータが表示されないことを確認できる唯一の方法は、端末を終了してリモートに再接続することです。ただし、バッファされたデータが表示されるのを待つよりもはるかに手間がかかります。

5
garethTheRed

私は通常、出力をlessに実行するため、lessを使用する代わりに、 q キー。

$ cmd | less

$ cat /dev/urandom | less

ss #2

打った後 q+Enter 終了して通常のターミナルに戻り、正常でクリーンな状態になります。

なぜそれが起こるのですか?

発生している問題は、ディスプレイの出力でキューに入れられているバッファー(STDOUT用)があることです。これらのバッファーはすぐにいっぱいになるため、停止するのに十分な速さでバッファーを中断することはできません。

ss #1

この効果を無効化/制限するには、stdbufを使用してSTDOUTバッファリングを無効にし、応答性を少し向上させる必要がありますが、これらの設定を試して、希望どおりの結果を得る必要があります。 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の記事 標準ストリームでのバッファリング をご覧になることを強くお勧めします。ニースの写真も含まれています。

参考文献

10
slm

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

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

これを今すぐ停止したい場合は、ターミナルエミュレータを終了します。そうしたくない場合は、少なくともウィンドウを最小化してください。インテリジェントターミナルエミュレーター(xtermなど)はウィンドウをマップしないため、X CPU時間を節約できるため、ガベージの表示が速くなります。 Xサーバーは優先度が高いため、xtermがバックグラウンドでデータを処理している間、これはマシンの応答性に大きな違いをもたらします。

これらすべてがリモートシェルで行われている場合、catによって生成されたデータは最初にSSH接続を経由する必要があるため、遅延はさらに悪化します。あなたのプレス Ctrl+C また、SSH接続を経由する必要があります。やや優先度が高くなりますが(帯域外に送信されます)、出力が蓄積されるまでにはまだ時間がかかります。 SSH接続を閉じる以外に、転送中のデータを抑制する方法はありません(これは、 Enter 次に~.)。

私は同じ問題を抱えていて、ここでの回答に満足できなかったので、さらに深く掘り下げました。他の人はすでにあなたのコマンドがあなたの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は期待どおりに動作し、バッファリングされているとしてもごくわずかなので、出力をすぐに強制終了します。

1
Eric

killcatコマンドへの方法を見つけるには十分です。
次の提案では、2番目の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)

    この場合、猫のPIDを殺す必要があるだけです:kill 23131

注意:

1
Hastur

Linuxには、正確にこの問題を解決するソフトウェアがあります(他にもいくつかあります)。 Windowsのターミナルエミュレータから呼び出すこともできます(Windowsを使用しているようです)。

SSHバイナリの代替となる mosh を試してください。 SSHとまったく同じように機能します(mosh user@hostname の代わりに ssh user@hostnameと期待どおりに機能し、秘密鍵認証なども行います。

基本的に、サーバーはパケットをバッファリングする別のプロセスを実行します。したがって、moshでCtrl + Cを押すと、リモートサーバーにこれが伝達され、追加の情報の送信が停止されます。さらに、キーストロークの結果を予測し、キーを押すたびに数ミリ秒節約できます。

欠点:現在、​​moshの使用中に履歴を上にスクロールすることはできません。

0
Saksham Sharma