
情境
您正在使用 Ubuntu LTS 14.04。您以 root 使用者登入。您執行以下命令:
exec su simple_user -c "/bin/bash /etc/init.d/simple_user_service"
這樣「simple_user_service」就以「simple_user」權限而不是root權限啟動。
問題
看來「exec su simple_user -c」不會為新的互動式 shell 終端取得 .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.
這真的很有趣,因為您可以將 BASH_ENV 設置為每次使用“su simple_user -c”時運行特定命令的文件,而無需加載完整的交互邏輯。
因此,在執行之前su simple_user -c
,您可以簡單地執行以下操作:
export BASH_ENV=~/.bash_script
並在 simple_user .bash_script 檔案中進行設置,例如:
export TEST="Hello"
然後,當我執行“simple_user_service”腳本時,“Hello”被正確列印。
這對我來說非常有用,因為我需要它來加載所有“rvm”環境(ruby)來運行特定的腳本。
想知道更多?
為什麼這麼麻煩?
因為我安裝了 ruby god:http://godrb.com/監視此特定腳本(延遲作業)。
我使用“rvm”來管理不同的紅寶石。
如有必要,腳本會透過執行自動刪除權限exec su application_user -c "/bin/bash application_script"
由於 god 需要以 root 權限運行,而 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
shell 定義在/etc/passwd
.
現在,當你這樣做時bash -c 'some_command'
,你基本上是在產生一個非互動式(而且當然未登入) 的會議bash
。由於在非互動模式下 shell 不會取得任何文件,因此不會如預期讀取任何文件。
請注意,~/.profile
源自 的登入互動式會話bash
,~/.bashrc
源自 的非登入互動式會話bash
。另請注意,Ubuntu 原始碼~/.bashrc
來自~/.profile
.
檢查INVOCATION
的部分man bash
以獲得更多想法。