新しいSSH開始ログインセッションに環境変数を渡すにはどうすればよいですか?

新しいSSH開始ログインセッションに環境変数を渡すにはどうすればよいですか?

現在の環境でFOO変数が定義(および -ed)されたとします。exportこの環境を環境と呼びますE0

ssh

% ssh [email protected]

新しく作成されたセッションの環境を呼び出しますE1

一般的に言えばFOOは で定義されておらず、特別なE1場合一般的に言えばFOOその値はin値とは無関係に設定されますE0

sshviaにログインしたときに変数がその値にFOO設定されるように(理想的には-edに設定されるように)、どのようにソートしますか?E1E0exportE1

重要な場合には、 と の両方zshを使用しています。E0E1

sshdこの質問に対する答えを得るには、そのプロセスで実行されるプロセスの構成を制御できないとしますfor.example.com。特に修正等が必要な/etc/ssh/sshd_configソリューションは除外されます。for.example.com

また、想定される値FOOは一定ではなく、ログインセッションごとに変わります。特にFOO全く設定しないこともありますがFOO、この場合の効果がまたはにE1似ていれば大丈夫です。FOO=export FOO=unset FOO


修正する:私はこれを試しました

% ssh [email protected] FOO=$FOO env

...実際に出力には、指定どおりに設定FOOされていると表示されます。しかし、ログインセッションを開始するときにこのアイデアをどのように適用するのかわかりません。特に、私が実行した場合

% ssh [email protected] FOO=$FOO

...コマンドは接続を確立せずに返されます。 (私はこれがリモートホストで実行される「コマンド」としてssh解釈されると仮定します。)FOO=$FOO一方、これを実行した後

% ssh [email protected] FOO=$FOO zsh

...リモートホストにシェルプロンプトが表示されません。コマンドはそこで中断されます。 (しかし、この前にパスワードプロンプトを受け取りましたssh。)最後のコマンドの他のバリエーションでも同じことが起こります。

% ssh [email protected] FOO=$FOO /path/to/zsh
% ssh [email protected] FOO=$FOO env zsh
% ssh [email protected] env FOO=$FOO zsh
% ssh [email protected] env FOO=$FOO zsh -l
% ssh [email protected] 'env FOO=$FOO zsh'

アップデート2:実際、「ぶら下がっている」ように見えるのは見えないプロンプトであることがわかりました。それでもコマンドを実行できます。また、ログイン時に実行されるzsh initファイルは通常の順序とは異なり、(驚くべきことではありません)環境は次のとおりです。本質的に(そして重要なのは、IOWが通常FOOよりもはるかに高いということです。)

アップデート3:dave_alcarinとmihhの助けを借りて、私はこれが私が追求したものと非常に近いことを知りました。

% ssh -t [email protected] env FOO=$FOO zsh -l -s

新しい環境と一般的な環境の間にはまだ解決すべきいくつかの重要な違いがありますが、これは私が望むものにかなり近いものです。

ベストアンサー1

SSHにはクライアントからサーバーに環境変数を渡す機能がありますが、OpenSSHはデフォルトのサーバー構成でこの機能を無効にしました。 1つの例外があります。TERMプロトコルは特別な場所を占めていますが、それを介してメッセージを転送することは、TERMクライアントがそれをデコードできることを確認する必要があるため、厄介です。

ただし、一部のサーバーは、特定の環境変数の通過を許可するように構成されています。たとえば、Debianはすべての名前を受け入れるようにSSHサーバーを設定しますLC_。通常、これはロケール変数ですが、必要な変数を入れることができます。

サーバーが変数を受け入れるように構成されていない場合は、その変数をコマンドの一部として渡すことができますが、いくつかの問題があります。問題は、コマンドをに渡すと、デフォルトでsshサーバーに端末が生成されないことです。実際にはシェルを実行しますが、シェルはターミナルではなくパイプで接続されているため、プロンプトを表示しないか、コマンドラインバージョンをサポートしていません。それにもかかわらず、コマンドを入力できます。入力してみるか+終了します。解決策は、オプションを使用して端末を開くようにSSHに明示的に指示することです。ssh [email protected] FOO=$FOO zshls Enterexit EnterCtrlD-t

ssh -t [email protected] FOO=$FOO zsh

ログインシェルによっては、以下を実行する必要があります。

ssh -t [email protected] FOO=$FOO exec zsh

追加のシェルプロセスを防ぐために、プロセスは明示的に呼び出されますzsh

まだ発生していない2番目の問題は参照です。 SSHプロトコルは、リモートシェルで実行されている文字列を送信します。ここで渡す文字列は、空白とFOO=の値で構成されます。したがって、値は変数に格納されている文字列ではなくシェルソースコードの一部として解釈されます。これは、値にシェル構文に特別な意味を持つ文字が含まれている場合に影響します。追加の参照レベルを追加する必要があります。ローカルシェルがzshであると仮定すると、パラメータ拡張フラグを使用できます。FOOexec zshFOOFOOq

ssh -t [email protected] FOO=${(q)FOO} exec zsh

直接のケースとの別の違いは、まずリモート側でログインシェルを実行し、それを非ログインシェルに置き換えることです。チェーンはログインシェル(必須)で始まるため.profile.zprofile実際には実行されますが、zshの対話型インスタンスはドットファイルの内容によって異なる可能性があるログインシェルではありません。最善の解決策は、おそらくドットファイルで壊れやすい作業を避けることです。を実行できますが、これを行うと、2番目のログインシェルが実行され、より大きな違いを簡単に作成できます(ORが尤度を保証することでこの問題をzsh -l解決することもできます)。.profile.zprofile

おすすめ記事