使用 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以获得更多想法。

相关内容