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


20

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

$ ssh example.com
user@example.com:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

user@example.com:~$ /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、にもにも$ PATHの変更はありません/etc/bash.bashrc。いいえ~/.ssh/environmentssh(1)環境変数があることを宣言しPATHています

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

しかし、このスレッドのStackOverflowからして、このメーリングリストの記事は、私がすることを示唆している必要があり、単になど/ etc / profileを、シェルのスタートアップファイルのいずれかを、変更することで、指定したコマンドの$ PATHに影響を与えることができること

何が起きてる?

回答:


16

ssh(1)マニュアルページから:「コマンドが指定されている場合、コマンドはログインシェルではなくリモートホストで実行されます。」

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

場合によっては-t、sshの動作(ttyの割り当て)についての議論もあります。

編集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にコンパイルされたものです。:)


うーん、「リモートホストで実行される」というフレーズは、言う以上に多くのことを意味すると思います。先ほど見逃していたより興味深い部分は、同じマンページの「環境」セクションにあります。「sshのコンパイル時に指定されたデフォルトのPATHに設定されたパス」。除き、この私がいることを示唆すべきコマンドのPATHに影響を与えることができること。
トラウトワイン

ポイントはログインシェルではないため、ログインシェルの場合と同じ方法で起動ファイルを実行/ソース/インクルードしないため、試してみることをお勧めします。物を入れること.bashrcもうまくいくかもしれませんが、全体的にPATHが重要な場合は回避します。または、sshを実行する「コマンド」方法が必要な場合は、絶対パス名を指定しないのはなぜですか?:)
マティアスアンバーグ

投稿を少し編集しました。現在、ログインシェル、非ログインシェル、およびそれらのインタラクティブ/非インタラクティブなバリアントがあります。SSHコマンドは、ユーザーのシェルで非対話型の非ログイン形式で呼び出されます。bash(1)呼び出しは何の起動ファイルは、この方法で読まれていないことを示唆しているが、私は上のドキュメントを見つけることができませんどのように sshがシェルを起動さを。これは、他の人が/ etc / ssh / sshrcスタートアップファイルソースを持っていない限り、上記のリンクされたソースに反するようです。(もちろん、回避策はありますが、ポイントはDebian SSHDがデフォルトでパスを処理する方法を正確に理解することです。)
troutwine

/etc/profileリモートボックスのパスの更新でPATHを変更するとssh user@remotebox 'env'、更新されたPATHが表示されます。export PATH=$PATH:/my/testpath.bashrc に追加した場合も同じことが言えます(ただし、私の場合は、対話型シェル(-z "$PS1")をチェックする前にファイルの一番上にあります)
Mattias Ahnberg

テスト/調査結果を更新しました。
マティアスアンバーグ

3

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

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

ここで、envは任意のコマンドに置き換えることができます。

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


3

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

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

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

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

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

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

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


0

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

#!/bin/bash -i

スクリプトの上部。これにより、スクリプトの実行時にシェルが対話モードになります。

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.