web-dev-qa-db-ja.com

複数のコマンドを端末に貼り付けると、Bashコマンドが切り捨てられます

次の100行をターミナル(xterm)にコピーして貼り付け、sshを介して接続しているサーバーで実行します。

mv /long/path/to/file1 /longer/path/to/file1
mv /long/path/to/file2 /longer/path/to/file2
...
mv /long/path/to/file99 /longer/path/to/file99
mv /long/path/to/file100 /longer/path/to/file100

残念ながら、コピー/貼り付け後、/longer/path/to/の下に100個のファイルが見つかりませんでした

Ssh経由で接続しているサーバーのbash履歴を見ると、最初の20個のコマンドの後、ほとんどのコマンドが切り捨てられていることがわかります。

mv /long/path/to/file1 /longer/path/to/file1
...
mv /long/path/to/file20 /longer/path/to/file20
mv /long/path/to/fi
mv /long/path/to/fi
mv /long/path/to/file23 /longer/p
mv /long/path/to/file24 /longer/path
mv /long/path/to/file25 /longer/p
mv /long/path/to/file26 /longer/p
mv /long/path/to/file27 /longer/path/t
mv /long/path/to/file28 /longer/path/to/fil
mv /long/path/to/file29 /longer/path/to/fil
mv /long/path/to/file30 /longer/path/to/file
mv /long/path/to/file31 /longer/path/to/file
...

この問題を回避する方法についての答えを見つけることができました:

しかし、私は正確に何が起こっているのかについての説明を見つけることができませんでした。特に:

  • それは端末関連の問題ですか(私の場合はXterm)?
  • コピー/貼り付けはsshで発生します:これは問題を生成または拡大しますか?
  • サーバー上のbash関連の問題ですか?別のシェルでは起こらないのではないでしょうか?
2
Gohu

このバグにぶつかったようです:

https://lkml.org/lkml/2013/7/25/205

readline()は、4kを超えるペーストがラインディシプリンバッファをオーバーランすると、誤ってエラー回復パスをトリガーします。エラー回復パスは、行規律バッファーがいっぱいで正規モードで動作していて、改行が受信されていない場合に入力を破棄します。 readline()はtermiosをnon-canonicalモードに変更して文字ごとに行を読み取るため、line disciplineバッファーがいっぱいになり、readline()がtermiosを呼び出し元のcanonicalモードに戻すと、今はいっぱいになります。 line discipline bufferは、エラー回復をトリガーします。

Termiosを非CanonモードからCanonモードに変更し、読み取りバッファーにデータが含まれている場合は、EOF Pushwithout読み取りバッファのDISABLED_CHAR。

Readline()の問題にとって重要なのは、読み取りバッファーを変更せずに、termiosを非正規モードに戻すことができることです。つまり、前のtermiosの変更が発生しなかったかのように(介在する読み取りが行われなかった場合)。

2013年12月10日にカーネルに適用されました。それはLinuxカーネル3.14でした。それより古いLinuxディストリビューションを使用していますか?あなたのディストリビューションは何ですか?あなたはおそらくあなたのファイルへの実際のパスを置き換えたので、私は実際に文字を数えることができません。できますか:

for ((a=1; a<20; a++)); do echo "mv /long/path/to/file$a /longer/path/to/file$a"; done|wc -c

あなたの本当の道で-それは本当に4kに近いものでしょうか?もしそうなら、上記のバグはおそらくあなたのものです。

もしそうなら、あなたの質問への答え:

  • それは端末関連の問題ですか(私の場合はXterm)?

番号

  • コピー/貼り付けはssh上で発生します:これは問題を生成または拡大しますか?

番号

  • サーバー上のbash関連の問題ですか?

いいえ、はい-これはbashまたはbashで使用されるlibのバグではありません。バグはカーネルにあります。

  • 別のシェルでは起こらないのではないでしょうか?

Shellがreadlineを使用していない場合はそうかもしれません。 zshのように。

関連する質問について「複数を貼り付ける方法...」は問題に関連していないようです-その原因は、一部のアプリが貼り付けたコマンドを読み取る可能性があるためです。リモートサーバーでsshコマンドを実行する場合、その最もよく知られている例はsshです。しかし、行の一部だけを失うことを考えると、それはあなたの場合にはありそうにありません。

2番目の質問「端末に貼り付けられたコマンド...」は2013年9月25日に尋ねられましたが、その時点ではパッチは存在せず、それは間違いなくあなたが持っているバグと私が疑うカーネルのバグのように見えます。

確実に確認する方法は? uname-aの出力をここに貼り付けます。

3
gena2x

手元の問題

コピーして貼り付けたコード行が切り捨てられる理由を知りたいと考えています。

私はあなたの問題を調べましたが、Bashには通常デフォルトで回線制限があることがわかりました。これはおそらくあなたの問題です。ただし、ここで示した例では、行がさまざまな長さで切り捨てられています。私はこれを打破するために最善を尽くします。

解決

1.端末関連の問題(私の場合はXterm)ですか?

おそらくそうですが、これはxtermではなくデフォルトのBash環境の制限によるものです。 (xtermの多くのデフォルトを変更していない限り)

切り捨てを減らすために行の長さを増やすためのソリューションを提供する次の投稿を参照しています。 このU&Lスタック交換の回答 ターミナルエミュレータが期待するものに一致するようにウィンドウサイズを変更することをカバーしています。ユーザーsaketrpは、ウィンドウサイズが端末によって正しく解釈されるようにするためのソリューションとしてこれを提供します。

Bashを使用している場合は、これを試すことができます。

$ shopt checkwinsize

あなたが得ない場合

checkwinsize    on

次に、それをアクティブにします

$ shopt -s checkwinsize

次に、別のコマンド(lsなど)を実行するか、ウィンドウのサイズを1回変更してみてください。上記は、毎回機能します。

特にRedhatシステムの場合、この問題は、〜/ .bashrcが/ etc/bashrcを呼び出さないように構成を誤ったことが原因であることがよくあります。通常、bashは/ etc/bashrcを呼び出すことが期待される〜/ .bashrcをロードします。これには、デフォルトでshopt -scheckwinsizeが含まれています。

ただし、これはウィンドウサイズの解釈にのみ影響し、実際の行の長さには影響しません。 このAskUbuntuの投稿 で提供される情報を使用して、shoptを正しく設定している場合は、次の行を.bashrcに追加して、行の長さを増やすことができます。

COLUMNS=250

source .bashrcを実行してBashプロファイルを更新します。

2.コピー/貼り付けはssh上で発生します:これは問題を生成または拡大しますか?

根本原因の一部ではないにしても、これは問題の一部であると言えます。リンクした回避策は、これが発生しないようにするための固溶体です。

コマンドのセットをコピーして貼り付ける必要がある場合(複数回使用する必要がありますか?)、コマンドのセットのBashスクリプトを作成することをお勧めします。次に、scpsftpcurl、電子メール、またはその他の方法を使用して、使用するファイルをリモートで転送します。

これにより、リンクされた回避策で概説されているように、切り捨ての問題が完全に回避され、スクリプトの作成や、多数のサーバーへのスクリプトの転送を一度にスクリプト化することもできます。

3.サーバー上のbash関連の問題ですか?別のシェルでは起こらないのではないでしょうか?

前に述べたように、はい、これはBashプロファイル設定によって設定された回線制限の問題である可能性があります。他のシェルにはこの問題がないかもしれませんが、私はDash/Bashに精通しているだけです。ただし、これらが実稼働サーバーまたはレガシーシステムである場合、環境変数を変更し始めると、常にうまくいくとは限りません。不可能ではないことは言うまでもありませんが、特定のパッケージ/ソフトウェア/以前のスクリプト/ cronjobがデフォルトのシェルであるBashに依存している場合はリスクがあり、これを変更すると結果が生じる可能性があります。

繰り返しになりますが、この問題を回避するには、実行するコマンドのスクリプトを作成し、リモートサーバーに転送してそこで実行することをお勧めします。

結論

コマンドが切り捨てられる理由は、環境、Bashプロファイル設定、ターミナルエミュレーター設定、およびコマンドのコピーと貼り付けの方法によって異なります。ご指摘のとおり、回避策があります。問題を回避するために、スクリプトと組み合わせて使用​​することをお勧めします。 xtermマンページへのリンク も含めているので、変更できる追加の設定やオプションがあるかどうかを確認できます。

この回答に関して質問や問題がある場合はコメントしてください。誤解を正し、投稿を改善するためのフィードバックに感謝します。必要に応じて回答を更新できます。

幸運を祈ります!

0
kemotep

ある端末から別の端末にコマンドをコピーするには、gzipとbase64を使用することをお勧めします。問題がメタ文字またはタブの展開に起因する場合は、この方法で解決する必要があります。

例:

[root@server-one ~]# cat << __EOF__ | gzip | base64
mv /long/path/to/file23 /longer/p
mv /long/path/to/file24 /longer/path
mv /long/path/to/file25 /longer/p
<other commands>
__EOF__

次に、エンコードされた結果をにコピーします

[root@server-two ~]$ base64 -di | gunzip | bash
<insert your base64-encoded and send with control-d>
0