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


18

問題

SSHを介して大量の情報を出力するコマンドを実行します。たとえば、100万回実行されるループ内にデバッグ情報を愚かに追加するか、単に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必要があります。これは、「この端末に書き込まれた出力を破棄する」ことを意味します。
マークPlotnick 14年

サーバーはDebian上で実行されます。質問を編集しました。Ctrl-Oも何もしないようです。おそらくそれはクライアントのものですか?
rr- 14年

-jジャンプスクロールを有効にするために、オプションでxtermを起動してみてください。基本的な問題は、ターミナルウィンドウが表示できるよりも速くリモートがデータを送信できることです。デフォルトでは、新しい行が印刷されるたびにウィンドウの内容をbitbltする必要があります。Ctrl-Cがリモートシステムに受信されるまでに、大量のデータがバッファリングされ、端末プログラムはすべてを表示しようとします。
マークプロトニック14年

ちょうどアイデア:通常、誤って実行する正確なコマンドがあり、それらが大量の出力を生成する場合、単にいくつかのエイリアスを追加しないのはなぜ.bashrcですか?
プシモン14年

sshの代わりにmosh
gmatht

回答:


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オプションの詳細については、manページを参照してください。

    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の記事をご覧になることを強くお勧めします。素敵な写真も含まれています。

参照資料


に追加|lessすることを覚えている限り、それは合理的ですcmd。実行するとcmd、計算結果の受信が完了するまで待つ必要があります^C
rr- 14年

1
それは実際に何が起こっているのかを説明していません。結局のところ、パイプは関係していないので、どのバッファーを参照していますか?
ジル 'SO-悪であるのをやめる' 14年

@Gilles-申し訳ありませんが、バッファは画面へのバッファになります。
slm

どんなバッファー?カーネルで?xtermで?
ジル 'SO-悪であるのをやめる' 14年

@Gilles-ちょっと待って、詳細を探している8
slm

3

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

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

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

これがすべてリモートシェルで行われると、ラグはさらに悪化します。なぜなら、によって生成されたデータcatは最初にSSH接続を通過する必要があるからです。Ctrl+を押してCもSSH接続を使用する必要があります。優先度はやや高くなります(帯域外に送信されます)が、出力が蓄積されるまでに時間がかかります。(あなたが押すことによって行うことができますSSH接続を閉じるのトランジット短いにおける抑制データに方法はありませんEnter、その後は~.)。


問題はSSHに関連しています。STDOUTバッファーは対話モードでは使用できませんが、SSHは対話モードを適切に処理できません。多くの出力がトランザクションでハングする可能性がありますが、Ctrl + Cを受け取るのはSSHプロセスであるため、Ctrl + Cをリモートに渡すことができない場合に出力を強制終了するのは彼の責任です。
user4674453

@ user4674453え?Ctrl + Cはローカル出力を強制終了するものではありません。それはまったくその仕事ではありません。これはリモート側に渡されることになっていますが、リモートプロセスを強制終了することもしないこともあります。
ジル「SO-悪であるのをやめる」

「リモート側に渡されることになっているため、リモートプロセスを強制終了することもしないこともあります。」-それを行うことも想定されていません。KILLシグナル、Ctrl + Cはそれらの1つを発行していますが、ローカルプロセス専用です。ローカルプロセスに使用されない場合、「想定」の概念はまったく適用されません。
user4674453

@ user4674453いいえ。Ctrl+ Cは強制終了信号ではありません。それは割り込み信号です。その役割は、対話型プロンプトに戻ることです。戻るための対話型プロンプトがないプログラムのみを強制終了します。
ジル「SO-悪であるのをやめる」

「これは割り込み信号です。」これはkillコマンドの引数であるため、killシグナルです。必要に応じて、POSIXシグナルとして呼び出されることもあります。「その役割は、対話型プロンプトに戻ることです。対話型プロンプトに戻らないプログラムのみを強制終了します。」丁度!!!そして、SSHは期待どおりにそれを行いません。
user4674453

1

コマンドへkillの道を見つけるのに十分なはずcatです。
次の提案では、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を殺すだけでよい場合: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を使用しているようですか?)。

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.