语境
您正在使用 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
以获得更多想法。