時々私は次のようなことをします
ssh user@host sudo thing
そして、sshはデフォルトでpseudo-ttyを割り当てないことを思い出しました。なぜできないのですか?エイリアスssh
を作成すると、どのようなメリットが失われssh -t
ますか?
ssh -t
常に実行するのは悪いコマンドです。一方、PTYを必要としないコマンドを実行すると、ターミナルが必要という明確なエラーメッセージが表示されます。
時々私は次のようなことをします
ssh user@host sudo thing
そして、sshはデフォルトでpseudo-ttyを割り当てないことを思い出しました。なぜできないのですか?エイリアスssh
を作成すると、どのようなメリットが失われssh -t
ますか?
ssh -t
常に実行するのは悪いコマンドです。一方、PTYを必要としないコマンドを実行すると、ターミナルが必要という明確なエラーメッセージが表示されます。
回答:
主な違いは、対話性の概念です。スクリプト内でコマンドをローカルで実行するのと、自分でコマンドを入力するのに似ています。リモートコマンドがデフォルトを選択する必要があり、非インタラクティブが最も安全であるという点で異なります。(そして通常最も正直な)
Ctrl-c
通常、ブレークによりsshコマンドのループがすぐにブレークしますが、代わりに制御シーケンスがリモートサーバーに送信されます。これにより、制御が sshコマンドを離れるときに、次のsshコマンドが開始する前に、キーストロークを「ハンマーで打つ」必要があります。ssh -t
cronなどの無人スクリプトでの使用には注意してください。入力のために対話的に動作するようにリモートコマンドを要求する非対話型シェルは、あらゆる種類のトラブルを要求しています。
独自のシェルスクリプトで端末の存在をテストすることもできます。bashの新しいバージョンでSTDINをテストするには:
# fd 0 is STDIN
[ -t 0 ]; echo $?
ssh
する場合ssh -t
、行末に余分なキャリッジリターンが期待できます。あなたには見えないかもしれませんが、そこにあります。^M
にパイプされると表示されcat -e
ます。次に、特にその出力をデータベースに挿入する場合、この制御コードが変数に割り当てられないようにするための追加の労力を費やす必要があります。これは以前と同じbashテストですが、STDOUTの場合です:
# fd 1 is STDOUT
[ -t 1 ]; echo $?
これらの問題を回避することは可能ですが、必然的にスクリプトを設計することを忘れることになります。ある時点で私たち全員がやる。また、チームメンバは、このエイリアスが存在することを認識または記憶していない場合があります。これにより、エイリアスを使用するスクリプトを記述するときに問題が発生します。
エイリアスssh
を作成することssh -t
は、ほとんど驚きのない設計原則に違反する場合です。人々は予期しない問題に遭遇し、何が原因なのか理解できないかもしれません。
他の回答で言及されていない利点の1つは、擬似端末なしで操作する場合、などのSSH エスケープ文字~C
がサポートされないことです。これにより、プログラムがこれらのシーケンスを含む可能性のあるバイナリファイルを安全に転送できます。
擬似端末を使用してバイナリファイルをコピーします。
$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.
擬似端末を使用せずにバイナリファイルをコピーします。
$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2
2つのファイルは同じではありません。
$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ
擬似端末でコピーされたものは破損しています。
$ chmod +x ~/free*
$ ./free
Segmentation fault
他方はそうではありません:
$ ./free2
total used free shared buffers cached
Mem: 2065496 1980876 84620 0 48264 1502444
-/+ buffers/cache: 430168 1635328
Swap: 4128760 112 4128648
これは、データ転送にSSH scp
などrsync
を使用するプログラムにとって特に重要です。SCPプロトコルがどのように機能するかのこの詳細な説明は、SCPプロトコルがテキストプロトコルメッセージとバイナリファイルデータの混合で構成される方法を説明します。
-t
フラグが使用されている場合でも、OpenSSH ssh
クライアントは、stdin
ストリームが端末ではないことを検出すると、擬似端末の割り当てを拒否することに注意してください。
$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb
以下を使用して、OpenSSHクライアントに強制的に擬似端末を割り当てることができます-tt
。
$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm
どちらの場合でも、(合理的に)リダイレクトされるかどうstdout
かstderr
は気にしません:
$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
リモートホストでは、次の設定を行う必要があります。
/etc/sudoers
...
Defaults requiretty
sudoなし
$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$
そしてsudoで
$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo
sudoを使用すると、余分な改行が返されます
$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
bar^M$
Connection to localhost closed.
解決策は無効にすることであるリターン改行キャリッジに改行変換するとstty -onlcr
$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
bar$
Connection to localhost closed.
下位互換性について考えてください。
sshの2つの主要なモードは、ttyを使用した対話型ログインと、ttyを使用しない指定コマンドです。これらはそれぞれrlogin
との正確な機能であったためrsh
です。sshは、置換として成功するためにrlogin
/ rsh
機能のスーパーセットを提供する必要がありました。
そのため、sshが生まれる前にデフォルトが決定されました。「コマンドを指定してtty を取得したい」などの組み合わせには、新しいオプションを使用してアクセスする必要がありました。を使用していたときとは異なり、少なくとも今はそのオプションがあることを嬉しく思いますrsh
。暗号化された接続を取得するための便利な機能を交換しませんでした。ボーナス機能があります!
からman ssh
:
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
これにより、リモートサーバーへの一種の「シェル」を取得できます。シェルアクセスを許可しないがSSHを許可するサーバーの場合(つまり、GithubはSFTPアクセスの既知の例です)、このフラグを使用すると、サーバーは接続を拒否します。
また、シェルにはすべての環境変数(など$PATH
)があるため、スクリプトの実行には通常、動作するためにttyが必要です。
non-interactive
、interactive
とlogin
。login
は、他の2つのシェルタイプの追加の特性です。これら3つの順列により、ログイン時にソースとなるファイルが決まります。これにより、環境の初期化方法が影響を受けます。(