TL; DR
使用しないでください-t
。-t
リモートホスト上の擬似端末を使用するため、端末からビジュアルアプリケーションを実行する場合にのみ使用する必要があります。
説明
改行文字(改行またはとも呼ばれます\n
)は、端末に送信されると、カーソルを下に移動するよう端末に指示する文字です。
しかし、seq 3
ターミナルで実行すると、のような場所にseq
書き込みが行われますが、表示されません:1\n2\n3\n
/dev/pts/0
1
2
3
しかし
1
2
3
何故ですか?
実際、seq 3
(またはssh host seq 3
そのことに関して)書き込む1\n2\n3\n
とき、端末はを参照し1\r\n2\r\n3\r\n
ます。つまり、改行はキャリッジリターン(カーソルを画面の左に戻す)と改行に変換されています。
これは、端末デバイスドライバーによって行われます。より正確には、端末(または擬似端末)デバイスの回線規律によって、カーネルに常駐するソフトウェアモジュール。
stty
コマンドを使用して、その回線制御の動作を制御できます。翻訳はLF
- > CRLF
をオンにします
stty onlcr
(通常、デフォルトで有効になっています)。次の方法でオフにできます。
stty -onlcr
または、次の方法ですべての出力処理をオフにすることができます。
stty -opost
それを実行して実行するとseq 3
、以下が表示されます。
$ stty -onlcr; seq 3
1
2
3
予想通り。
今、あなたがするとき:
seq 3 > some-file
seq
端末への書き込みではなく、ファイルへの書き込みです。変換は行われていません。だから、some-file
含まれていません1\n2\n3\n
。変換は、端末デバイスへの書き込み時にのみ行われます。そして、それは表示のためだけに行われます。
同様に、あなたがするとき:
ssh host seq 3
ssh
が1\n2\n3\n
何にssh
出力されるかに関係なく書き込みを行っています。
実際に起こることは、seq 3
コマンドがhost
パイプにリダイレクトされたstdoutで実行されることです。ssh
ホスト上のサーバーは、パイプのもう一方の端を読み取り、自分のに暗号化されたチャネルを介してそれを送信するssh
クライアントとssh
クライアントがあなたのケースでは、その標準出力に疑似端末デバイス、それを書き込み、LF
sはに翻訳されてCRLF
表示するために。
多くの対話型アプリケーションは、stdoutが端末でない場合に異なる動作をします。たとえば、次を実行すると:
ssh host vi
vi
それが気に入らない、パイプに出力されるのが気に入らない。たとえば、カーソルポジショニングエスケープシーケンスを理解できるデバイスとは通信していないと考えています。
そのssh
ための-t
オプションもあります。このオプションを使用すると、ホスト上のsshサーバーは擬似端末デバイスを作成し、その標準出力(および標準入力、標準エラー出力)を作成しvi
ます。何vi
その端末デバイスに書き込みすると、そのリモート仮想端末回線の規律を経て、によって読み取られssh
、サーバーとの暗号化チャネルを介して送信されるssh
クライアント。パイプを使用する代わりに、ssh
サーバーがpseudo-terminalを使用することを除いて、以前と同じです。
もう1つの違いは、クライアント側では、ssh
クライアントが端末をraw
モードに設定することです。これは、そこで翻訳が行われないことを意味しopost
ます(無効化され、他の入力側の動作も行われます)。たとえばCtrl-C、割り込みssh
ではなくを入力すると、その^C
文字はリモート側に送信され、リモート擬似端末の回線制御が割り込みをリモートコマンドに送信します。
行うとき:
ssh -t host seq 3
seq 3
1\n2\n3\n
擬似端末デバイスであるstdoutに書き込みます。以下のためonlcr
に翻訳されることを、ホスト上に1\r\n2\r\n3\r\n
、暗号化チャネルを介してあなたに送信。あなたの側には翻訳がありません(onlcr
無効になっている)ので、1\r\n2\r\n3\r\n
そのままで(raw
モードのため)そのまま表示され、ターミナルエミュレータの画面に正しく表示されます。
今、あなたがするなら:
ssh -t host seq 3 > some-file
上記と違いはありません。ssh
は同じことを書きます:1\r\n2\r\n3\r\n
が、今回はにsome-file
。
したがって、基本的LF
にの出力のすべてはにseq
変換さCRLF
れていsome-file
ます。
行う場合も同じです:
ssh -t host cat remote-file > local-file
すべてのLF
文字(0x0aバイト)はCRLF(0x0d 0x0a)に変換されています。
これがおそらくファイルの破損の原因です。2番目に小さいファイルの場合は、ファイルに0x0aバイトが含まれていないため、破損はありません。
tty設定が異なると、さまざまな種類の破損が発生する可能性があることに注意してください。別の潜在的な破損のタイプは-t
、host
(~/.bashrc
、~/.ssh/rc
...)のスタートアップファイルがstderrに書き込みを行う場合です。これ-t
は、リモートシェルのstdoutとstderrが最終的にssh
stdout にマージされるためです(両方ともpseudo -端末デバイス)。
そこにあるリモートcat
から端末デバイスへの出力は望ましくありません。
あなたが欲しい:
ssh host cat remote-file > local-file
できること:
ssh -t host 'stty -opost; cat remote-file` > local-file
それは動作します(上記で説明したstderr破損ケースへの書き込みを除く)が、それでも、不要な擬似端末層が実行されているので、最適ではありませんhost
。
もう少し楽しい:
$ ssh localhost echo | od -tx1
0000000 0a
0000001
OK。
$ ssh -t localhost echo | od -tx1
0000000 0d 0a
0000002
LF
に翻訳 CRLF
$ ssh -t localhost 'stty -opost; echo' | od -tx1
0000000 0a
0000001
OK
$ ssh -t localhost 'stty olcuc; echo x'
X
これは、端末回線制御によって実行できる出力後処理の別の形式です。
$ echo x | ssh -t localhost 'stty -opost; echo' | od -tx1
Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Inappropriate ioctl for device
0000000 0a
0000001
ssh
自身の入力が端末でない場合に、擬似端末を使用するようサーバーに指示することを拒否します。あなたはそれでも強制することができ-tt
ます:
$ echo x | ssh -tt localhost 'stty -opost; echo' | od -tx1
0000000 x \r \n \n
0000004
回線制御は入力側でより多くのことを行います。
ここでecho
は、入力を読み取らず、出力するx\r\n\n
ように求められなかったので、どこから来たのですか?これecho
は、リモートの擬似端末(stty echo
)のローカルです。ssh
サーバが供給されx\n
、それが遠隔疑似端末のマスタ側にクライアントから読み取ら。そして、そのラインの規律はそれをエコーバックします(前stty opost
に実行されるCRLF
ので、aが表示され、not は表示されませんLF
)。これは、リモートアプリケーションがstdinから何かを読み取るかどうかとは無関係です。
$ (sleep 1; printf '\03') | ssh -tt localhost 'trap "echo ouch" INT; sleep 2'
^Couch
0x3
文字は、次のようにエコーバックされる^C
(^
とC
)のためstty echoctl
とシェルと睡眠があるためSIGINTを受け取りますstty isig
。
それで:
ssh -t host cat remote-file > local-file
十分に悪いですが、
ssh -tt host 'cat > remote-file' < local-file
他の方法でファイルを転送するのは非常に悪いことです。> LF翻訳するだけでなく、すべての特殊文字での問題( -あなたは、いくつかのCRを得るでしょう^C
、^Z
、^D
、^?
、^S
も...)とは、リモートでcat
の最後の時にEOFは表示されませんlocal-file
達している場合にのみ、^D
後に送信され\r
、\n
または、端末で^D
行うときなどcat > file
。
-t
転送を中断するのはオプションです。非常に特定の理由で必要でない限り、-t
またはを使用しないでください-T
。デフォルトはほとんどの場合に機能するため、これらのオプションはほとんど必要ありません。