su -c を使用するとき、どのファイルがソースになりますか?

su -c を使用するとき、どのファイルがソースになりますか?

コンテクスト

Ubuntu LTS 14.04 で作業しています。root ユーザーとしてログインしています。次のコマンドを実行します。

exec su simple_user -c "/bin/bash /etc/init.d/simple_user_service"

これにより、「simple_user_service」は root 権限ではなく、「simple_user」権限で起動されます。

質問

「exec su simple_user -c」は、.bashrc や .profile、または新しい対話型シェル端末用の通常ソースとなる他のファイルをソースしないようです。 simple_user .bashrc ファイルに次の行を追加して確認しました。

export TEST="Hello"

次に、「simple_user_service」初期化スクリプトで次の操作を実行します。

#!/bin/bash
### BEGIN INIT INFO
# Provides:             test_script
# X-Interactive:        true
# Short-Description:    Test script
### END INIT INFO

echo $TEST

スクリプトを実行しても何も印刷されませんが、次のコマンドを実行すると:

su simple_user
echo $TEST
> Hello

TEST 変数が正しく設定され、印刷されます。

そこで疑問に思ったのですが、「exec su simple_user -c」コマンドは simple_user プロファイル/bashrc ファイルをソースとして取得するのでしょうか? もしそうなら、それがどれかを知る方法はありますか?

ご協力ありがとうございました!

[編集 - 2時間後]

受け取った回答のおかげで、「man bash」の指示をより正確に理解できました。次のことがわかりました。

   When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it  appears  there,  and
   uses the expanded value as the name of a file to read and execute.  Bash behaves as if the following command were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
   but the value of the PATH variable is not used to search for the file name.

完全な対話型ロジックをロードする必要なく、「su simple_user -c」を使用するたびに特定のコマンドを実行するファイルに BASH_ENV を設定できるため、非常に興味深いです。

したがって、 を実行する前にsu simple_user -c、次のように実行します。

export BASH_ENV=~/.bash_script

そして、 simple_user .bash_script ファイルに次のように設定します。

export TEST="Hello"

次に、「simple_user_service」スクリプトを実行すると、「Hello」が正しく印刷されます。

特定のスクリプトを実行するためにすべての「rvm」環境 (ruby) をロードする必要があったため、これは私にとって非常に役に立ちました。

もっと知りたい?

なぜこんなに面倒なことが起こるのでしょうか?

ruby godをインストールしたので:翻訳元この特定のスクリプト(遅延ジョブのスクリプト)を監視します。

そして、私はさまざまなルビーを管理するために「rvm」を使用しています。

そしてスクリプトは必要に応じて自動的に権限を削除します。exec su application_user -c "/bin/bash application_script"

god はルート権限で実行する必要があり、rvm は .bashrc/.profile ファイルでのみロードされるため、スクリプトで rvm 環境を適切にロードする方法が必要でした。スクリプトに rvm load コマンドを追加するだけで済みますが、そうするとスクリプトが環境に依存することになり、受け入れられませんでした。

そこで、権限が削除される前にスクリプトにこれを追加しました:

if [ -e "config/BASH_ENV" ]; then
  export BASH_ENV=$(cat config/BASH_ENV)
fi

そのおかげで、config/BASH_ENV ファイルに設定したファイルに rvm をロードできます。たとえば、次のようになります。

# In config/BASH_ENV file of your rails app:
export BASH_ENV="~/.bash_script"

# In /home/simple_user/.bash_script 
[[ -s "/etc/profile.d/rvm.sh" ]] && . "/etc/profile.d/rvm.sh" # Load RVM function

すると、私のスクリプトと神は期待通りに動作します。

読者が本当の質問に集中できるように、私は答えを得る前にそれらのことをすべて説明しませんでした。

しかし、そのおかげで良い答えが得られ、良い解決策が見つかったので、他の人にも役立つようにこの編集を書きました。

再度、感謝します!

答え1

次の操作を行うと:

su some_user -c 'some_command'    

some_command次のように実行されます:

bash -c 'some_command'

が のシェルで定義されているbashと仮定します。some_user/etc/passwd

そうすると、bash -c 'some_command'基本的には非インタラクティブ(そしてもちろん非ログイン) セッションbash。非対話モードではシェルによってファイルがソース化されないため、予期されるファイルは読み取られません。

~/.profileは のログイン、対話型セッションでソース化されbash、は の~/.bashrc非ログイン、対話型セッションでソース化されることに注意してくださいbash。また、Ubuntu は~/.bashrcからソース化されることにも注意してください~/.profile

INVOCATIONさらに詳しい情報を得るには、のセクションを確認してくださいman bash

関連情報