
コンテクスト
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
。