現在の環境でFOO
変数が定義(および -ed)されたとします。export
この環境を環境と呼びますE0
。
今ssh
。
% ssh [email protected]
新しく作成されたセッションの環境を呼び出しますE1
。
一般的に言えばFOO
は で定義されておらず、特別なE1
場合一般的に言えばFOO
その値はin値とは無関係に設定されますE0
。
ssh
viaにログインしたときに変数がその値にFOO
設定されるように(理想的には-edに設定されるように)、どのようにソートしますか?E1
E0
export
E1
重要な場合には、 と の両方zsh
を使用しています。E0
E1
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 zsh
ls
Enterexit
EnterCtrlD-t
ssh -t [email protected] FOO=$FOO zsh
ログインシェルによっては、以下を実行する必要があります。
ssh -t [email protected] FOO=$FOO exec zsh
追加のシェルプロセスを防ぐために、プロセスは明示的に呼び出されますzsh
。
まだ発生していない2番目の問題は参照です。 SSHプロトコルは、リモートシェルで実行されている文字列を送信します。ここで渡す文字列は、空白とFOO=
の値で構成されます。したがって、値は変数に格納されている文字列ではなくシェルソースコードの一部として解釈されます。これは、値にシェル構文に特別な意味を持つ文字が含まれている場合に影響します。追加の参照レベルを追加する必要があります。ローカルシェルがzshであると仮定すると、パラメータ拡張フラグを使用できます。FOO
exec zsh
FOO
FOO
q
ssh -t [email protected] FOO=${(q)FOO} exec zsh
直接のケースとの別の違いは、まずリモート側でログインシェルを実行し、それを非ログインシェルに置き換えることです。チェーンはログインシェル(必須)で始まるため.profile
、.zprofile
実際には実行されますが、zshの対話型インスタンスはドットファイルの内容によって異なる可能性があるログインシェルではありません。最善の解決策は、おそらくドットファイルで壊れやすい作業を避けることです。を実行できますが、これを行うと、2番目のログインシェルが実行され、より大きな違いを簡単に作成できます(ORが尤度を保証することでこの問題をzsh -l
解決することもできます)。.profile
.zprofile