おそらくこれは私が達成しようとしている奇妙なことですが、
SSHを介してリモートホストに接続し、「alias」などのいくつかのbashコマンドを自動化してインタラクティブモードで使用したいと思います。リモートホストはプライベート環境を許可しません。
可能ですか?そうなると「予想」されますか?それともこれを達成する他の方法はありますか?
デフォルトでは、bashrcがリモートホスト上のファイルを変更しないことを願っています。
答え1
つまり、リモコンが欲しいのですが、~/.bashrc
別の名前でも持てないのです。 Bashは、初期コマンドをコマンドライン引数として渡したり、環境変数を介して渡したりすることをサポートしておらず、ファイル内になければなりません。しかし、ファイルがファイルシステムにある必要はありません!
bash --rcfile /dev/fd/3 3< <(echo 'alias foo="echo hello"')
$ foo
hello
LC_XXX
多くのSSHサーバーはロケール設定を表すためによく使用され、ホスト間で転送する必要があり、セキュリティに影響を与えないため、名前付き環境変数の転送を許可します。許可する場合は、環境変数を介してコンテンツを転送し.bashrc
てから、その環境変数をファイル記述子に提供できます。
LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
'exec bash --rcfile /dev/fd/3 3< <(printf %s "$LC_BASHRC")'
- ローカルコンテンツは
~/.bashrc
環境変数を介してサーバーに送信されますLC_BASHRC
。 exec 3<&-
ファイルを読んだ後にファイル記述子を閉じるには、追加してください。- リモート側では、ログインシェルは
exec
ファイル記述子3の初期化ファイルを読み取るための新しいbashインスタンスに置き換えられます()。 3< <(…)
ファイル記述子 3 の出力をコマンドでリダイレクトします。printf
親プロセスにパイプされます。
サーバーのログインシェルが/bin/sh
bash または ksh でない場合は、そのシェルで直接プロセス置換を使用できないため、追加の階層が必要です。
LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
'exec bash -c '\''exec bash --rcfile /dev/fd/3 \
3< <(printf %s "$LC_BASHRC")'\'
/etc/sshd_config /etc/ssh/sshd_config`AcceptEnv directive in its [
設定を見つけて、SSHサーバーでどの環境変数が許可されているかを確認できます。](http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&sektion=5) (
or
3< <(…)
コマンド置換を使用する代わりに、この文字列を使用できます。これはパイプではなく一時ファイル($TMPDIR
または/tmp
)を生成するため、一時ファイルの作成を気にしない場合にのみ機能します。
LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
'exec bash --rcfile /dev/fd/3 3<<<"$LC_BASHRC"'
一時ファイルを生成しても問題ない場合は、次の簡単な方法があります。
- ファイルを
.bashrc
一時リモートファイルにコピーします。一時ファイルが削除されるまで、これは一度だけ実行できます。 - 対話型シェルを起動し、
--rcfile
一時ファイルをポイントします。
remote_bashrc=$(ssh remote.example.com 'bashrc=$(mktemp) && cat >>"$bashrc" && echo "$bashrc"' <~/.bashrc)
ssh -t remote.example.com "exec bash --rcfile '$remote_bashrc'"
SSH実装が古すぎない場合は、次のことができます。デフォルト接続の使用同じホストに対する複数のSSHコマンドの実行を高速化します。
鍵でログインして公開鍵ファイルを制御できる場合は、さらに自動化できます。存在する~/.ssh/authorized_keys
、キーには、command=…
コマンドラインで指定されたコマンド以外のコマンドを実行できるディレクティブがあります。バラよりリモートrsyncプロセスの環境変数を設定するには?もっと説明したい。
command="if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
eval \"$SSH_ORIGINAL_COMMAND\";
else exec bash -c 'bash 3<<<\"$LC_BASHRC\"'; fi" ssh-rsa …
または
command="if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
eval \"$SSH_ORIGINAL_COMMAND\";
else exec bash -c 'bash 3<<<\"alias foo=bar; …\"'; fi" ssh-rsa …
(これは一行に書く必要があります。読みやすくするために改行しました。)
答え2
Gillesのソリューションに基づいてAcceptEnv
サーバーに追加する必要はありませんLC_XXX
。
ssh -t remote.example.com "
exec bash --rcfile <(
printf '%s\n' '$(
sed "s:':'\\\\'':g" ~/.bashrc
)'
)
"
~/.bashrc
これはリモートセッションでローカルを使用することです。 bashの一重引用符の間のすべての内容が文字通り処理されることを利用するので、エスケープについて心配する必要がある唯一のものは内部一重引用符自体です。 bashコードをで囲み、'
s'
を内部sに置き換えて'\''
安全に参照できます。
エイリアスまたはインラインコンテンツを追加する場合離れて ~/.bashrc
:
ssh -t remote.example.com "
exec bash --rcfile <(
printf '%s\n' '
. ~/.bashrc
alias ll=\"ls -l\"
'
)
"
答え3
ssh_configのマニュアルページの.fromSendEnv
でこれを行うことができます。.ssh/config
SendEnvは、ローカル環境(7)のどの変数をサーバーに送信する必要があるかを指定します。環境配信はプロトコル 2 でのみサポートされます。サーバーもこれをサポートする必要があり、サーバーはこれらの環境変数を受け入れるように構成する必要があります。サーバーの構成方法については、sshd_config(5)のAcceptEnvを参照してください。変数は、ワイルドカード文字を含めることができる名前で指定されます。複数の環境変数をスペースで区切ったり、複数のSendEnvディレクティブに配布したりできます。デフォルトでは、環境変数は送信されません。