使用 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」就以「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'

假設bashsome_usershell 定義在/etc/passwd.

現在,當你這樣做時bash -c 'some_command',你基本上是在產生一個非互動式(而且當然未登入) 的會議bash。由於在非互動模式下 shell 不會取得任何文件,因此不會如預期讀取任何文件。

請注意,~/.profile源自 的登入互動式會話bash~/.bashrc源自 的非登入互動式會話bash。另請注意,Ubuntu 原始碼~/.bashrc來自~/.profile.

檢查INVOCATION的部分man bash以獲得更多想法。

相關內容