web-dev-qa-db-ja.com

sshリモートコマンドの$ PATHがインタラクティブシェルの$ PATHと異なるのはなぜですか?

ドットファイルの$ PATHに変更を加えていないユーザーがいます。これは、まさにシステムのデフォルト設定です。ログインシェルから:

_$ ssh example.com
[email protected]:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$Shell"
echo "$PATH"

[email protected]:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin
_

_/etc/profile_で指定されているとおり。これはかなり予想外です。

_$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
_

私が言ったように、_~/.bashrc_でも_/etc/bash.bashrc_でも$ PATHの変更はありません。 _~/.ssh/environment_もありません。 ssh(1)は、環境変数PATH

Sshのコンパイル時に指定されたデフォルトのPATHに設定します。

しかし このスレッド からStackOverflowおよびこの メーリングリスト の記事は、私がすべきである影響を与えることができることを示唆しています/ etc/profile、シェルスタートアップファイルの1つなどを変更するだけで、特定のコマンドの$ PATH.

何が起きてる?

20
troutwine

ssh(1)のマニュアルページから: "コマンドを指定すると、ログインシェルではなくリモートホストで実行されます。"

つまり、実際にマシンにログインすると、bashはログインシェルとして起動され、適切なファイルをロードします。リモートで接続してコマンドを発行すると、bashの代わりに実行されます。つまり、これらのファイルはロードされません。 sshのコマンド部分でsu -l -cまたは同様のものを使用すると、この問題を回避できます。

場合によっては、sshの動作(ttyの割り当て)の-t引数も確認しました。

編集1
あなたが見つけたPATH情報は、デフォルトのパス(それを上書きしない限り)はsshdにコンパイルされたものだと思います。/etc/profile、/ etc/bash *、ローカルドットファイルなどにPATH情報が含まれていないことを確認した後、ログオンしてもPATHが残っていました。私はこれをsshdで検索し、そこで見つけました。つまり、マンページは次のように述べています。

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

次に、PATH=$PATH:/my/testをリモートの.bashrcファイルの一番上に追加し、もう一度確認します。

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

だから私はそれに絶対に影響を与えることができ、デフォルトのPATHはsshdにコンパイルされたものです。 :)

16
Mattias Ahnberg

私は問題を解決するために別の解決策を思いつきました。私の個人的な好みは、既存の構成ファイルを変更するのではなく、新しい構成ファイルを作成することです。このようにして、デフォルト構成からの変更を簡単に変更できます。

/etc/profile.d/ssh_login.shの内容は次のとおりです:

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

openssh-serverの代わりにdropbearを使用すると(opensshでも動作するはずです)、リモートでログインすると、SSH_CONNECTION変数が自動的に設定されます。 SSHログインを検出し、画面に情報を表示し、最も重要なこととして、/etc/environmentからグローバル環境設定をロードしてコンパイル済みの値を置き換えるために、新しいシェルプロファイル構成を作成しました。これは、リモートコマンドの実行ではなく、インタラクティブなSSHシェルにのみ影響することに注意してください。

または、opensshを使用していて、対話型シェルであるかどうかに関係なく、常にグローバル環境をロードする場合は、次のように~/.ssh/にシンボリックリンクを配置できます。

ln -s /etc/environment ~/.ssh/environment

次に、/etc/sshd/sshd_configPermitUserEnvironmentオプションを有効にする必要があります。ただし、LD_PRELOADなどのメカニズムを使用する一部の構成では、アクセス制限を回避できるため、信頼できるユーザーに対してのみこれを実行してください。詳細については、man sshd_configを参照してください。具体的には、Matchブロックを使用してオプションを特定のユーザー/グループに制限する方法をご覧ください。

3
tachylatus

次のコマンドを実行することで、sshにリモートパスを使用してコマンドを実行させることができました。

ssh dist@d6 "bash --login -c 'env'"

ここで、envは、必要なコマンドに置き換えることができます。

私は認証済みのキーを持っているので、コマンドやsshを実行するのにパスワードは必要ありませんでした。

3
Ian

プロファイルパスをロードする場合は、以下を試してください。

#!/bin/bash -i

スクリプトの上部。このように、スクリプトを実行すると、シェルは対話モードになります。

Bashが対話型ログインシェルとして、または--loginオプションを使用して非対話型シェルとして呼び出されると、ファイル/ etc/profileが存在する場合、そのファイルからコマンドが最初に読み取られて実行されます。そのファイルを読み取った後、〜/ .bash_profile、〜/ .bash_login、および〜/ .profileをこの順序で検索し、存在し、読み取り可能な最初のコマンドからコマンドを読み取って実行します。シェルの起動時に--noprofileオプションを使用して、この動作を禁止できます。

http://linux.die.net/man/1/bash

0
Adam Brand