
私はこれを持っています:
ssh -i "alex-kp.pem" '[email protected]' '
cd codes/vbe
eval $(ssh-agent)
ssh-add -D
ssh-add ~/.ssh/id_vbe
'
コマンドを実行してセッションを終了するので、ローカルコンピュータに戻ります。理由を知っている人はいますか?
答え1
リモートシステムで実行するコマンド(つまり一連のコマンド)を提供しました。コマンド(これらのコマンド)が完了すると、セッションは終了します。これは定義されており、予想される動作でなければなりませんman ssh
。以下を参照してください。
コマンドを指定すると、ログインシェルではなくリモートホストで実行されます。
hostname
リモートシステムで実行されるより簡単な例
ssh -i alex-kp.pem [email protected] hostname
答え2
遠隔側では何が起こるのか
Localはssh user@server 'shell_code'
SSHサーバーを次のように実行します。
"$SHELL" -c 'shell_code'
私はそう言うわけではない正確にこれと同じですが、何が起こっているのかを理解するのに十分なほど近いです。まるでシェルから呼び出すかのように書いたので、おなじみのようですが、実際にはまだシェルはありません。
この方法で呼び出されたシェルに達しましたshell_code
。あなたの場合、コードは複数行で、何も変更されません。
plainなどのシェルコードがない場合、ssh user@server
SSHサーバーは別のものを起動します。
"$SHELL" -i
もう一度申し上げますが、そうではないと申し上げたいです。正確にこのように。
この方法で呼び出されたシェルは次のとおりです。インタラクティブシェルはプロンプトを印刷し、入力を待ちます。これがあなたが達成したい行動のようです。
SSHサーバーは、ローカル通話形式に応じて意図的に1つの形式を使用しますssh
。後者の形式は対話型の使用に非常に適しており、電子形式は、一部の非対話型シェルコードをローカルのようにリモートで実行することもできます。たとえば、ローカルで次のことができます。
<data md5sum
ただし、ローカルで欠落している場合はmd5sum
リモートを使用できます。
<data ssh user@server md5sum
md5sum
タスクの完了後、ローカルシャットダウンと同様に、リモートもタスクのssh … md5sum
完了md5sum
後に終了します。とても便利です。
または、リモートファイルにパイプすることもできます。
<data ssh user@server 'cat >copy'
また、cat
リモートシェルとローカルシェルは、ssh
適切な場合は自動的にシャットダウンされます。
または、サーバーに時間を要求することもできます。
ssh user@server date
これはlocalのように動作し、date
対話型リモートシェルには入りません。
対話型シェルが自動的に終了する場合
私は[
ssh … date
]がデフォルトで終了しないと予想しました。端末にコマンドを入力するとデフォルトで終了しますか?
もちろん。コマンドの読み込み中にEOFに達すると、対話型シェルは終了します。問題は、Ctrl+()を押すdまで端末でEOFを「経験」しないことです。1回または2回)。これが端末で動作する方法です。ただし、インタラクティブシェルが通常のファイルまたはパイプから読み取られるようにすると、予想される瞬間に正確にEOFが表示されます。
{ echo date; echo sleep 5; echo date; } | bash -i
これで終了します。
したがって、実際にやることがない場合、すべてのシェルはデフォルトで終了します。端末からデータを読み取ると、対話型シェルは「終了しません」と呼ばれます。意図的に入力がいつでも現れる可能性があると仮定して、現在の入力がないときにEOFをトリガしないように設計されています。これは、シェルや一般的なプログラムではなく、端末に関連しています。つまり、シャットダウンのようなものですが、</etc/fstab cat
ttyからの一般的な読み取りは無期限に機能します。同じ話です。cat
リモートttyの重要性
SSHサーバーがシェルを実行する2つの方法は、単純な形式以上の違いがあります。リモートインタラクティブコマンドは、ローカルttyを使用するとうまく機能します(したがって、ローカルssh
とコマンドの間のサーバー側ttyです)。ただし、md5sum
リモート非対話型コマンド(例)は、ttyが割り当てられていない場合でもうまく機能します。 SSHサーバーはttyを割り当てたり割り当てたりせず、自動的に割り当てられます(ただし、必要に応じてssh
オプションで明示的に選択できます)。私は2つを最大限に活用しようとし、質問(そして答え)から洞察を得ることができると思います。-t
-tt
-T
SSH には独立した stdin、stdout、stderr、tty があります。。
あなたは何ができますか?
最初のプロンプトを表示する前に、一部のシェルコードを実行するリモートインタラクティブシェルが必要なようです。最も簡単な方法は、コードを正しい起動スクリプト(~/.bashrc
シェルがBashの場合)に配置しssh
(シェルコードを渡さずに)対話型リモートシェルに配置することです。これは永続的なソリューションであるため、リクエスト時にワンタイムコードを実行してメッセージを引き続き受信したい場合は便利ではありません。
要求時にシェルコードを実行するには、次のものが必要です。
ssh -t … '
exec bash --rcfile <(cat <<"EOF"
# your custom shell code here
. ~/.bashrc
# and/or here
EOF
) -i'
これは、SSHサーバーによって開始されたシェルがこれを理解し<(…)
(Bashがこれを理解する)、最終的な対話型シェルとして必要なシェルがBashであると仮定します。
SSHサーバーはまだttyを使用する非対話型シェルを実行します-t
。シェルはexec
代わりにカスタムファイルをインポートするための対話型Bashを使用します~/.bashrc
。ファイルはプロセス交換のパイプになり、その内容はカスタムシェルコードとソースガイドラインになります~/.bashrc
。これにより、最終シェルはカスタムシェルコードを実行し、プロンプトを表示します。
SSHサーバーによって直接作成された対話型シェルはログインシェルであり、/etc/profile
ここでは両方のシェルがログインシェルではありません。を使用して最終シェルを実行できますが、-l
それを無視します--rcfile
。
しかし、あなたの特定カスタムシェルコードは生き残るように設定しますexec
(しばしば継承できます)。これは、コードスニペットを次のように単純化できることを意味します。
ssh -t … '
cd codes/vbe
eval $(ssh-agent)
ssh-add -D
ssh-add ~/.ssh/id_vbe
exec bash -i
'
この場合-l
、必要に応じて最終的なBashをログインシェルとして追加して作成できると思います。ログインシェルと非ログインシェルは異なるファイルを持つことに注意してください。これらのファイルは互いに生成できます(つまり、~/.bash_profile
互いに生成できます~/.bashrc
)。非対話型Bashもソースを提供できます。~/.bashrc
;そして、2つのリモートシェルが順番にあり、それぞれが何かを得ることができます。リモコンは~/.bashrc
おそらく2回購入するでしょう。含有量によっては副作用が発生する場合があります。
ssh …
まったく別の方法は、ローカルスクリプトから呼び出すことです(シェルコードは不要です)expect
。このスクリプトは必要なシェルコードを挿入し、最終的には一致を介してinteract
リモートプロンプトを検出できると仮定します@*:*$
。
expect -c '
spawn ssh -i alex-kp.pem [email protected]
expect "@*:*$ "
send "cd codes/vbe\r"
expect "@*:*$ "
send "eval \$(ssh-agent)\r"
expect "@*:*$ "
send "ssh-add -D\r"
expect "@*:*$ "
send "ssh-add ~/.ssh/id_vbe\r"
interact
'
AWSはわかりませんが、通常、切断後も生き残ることも、そうでない場合もありますssh-agent
。eval $(ssh-agent)
生き残るには、ssh-agent -k
リモートシェルを終了する前に手動でclean()することをお勧めします。