# running script as root,but switching to a different user... su - $different_user echo $HOME # returns /root/ but should be /home/myuser
更新:
似乎问题是,我试图切换用户在我的脚本的方式:
$different_user=deploy # create user useradd -m -s /bin/bash $different_user echo "Current user: `whoami`" # Current user: root echo "Switching user to $different_user" # Switching user to deploy su - $different_user echo "Current user: `whoami`" # Current user: root echo "Current user: `id`" # Current user: uid=0(root) gid=0(root) groups=0(root) sudo su $different_user # Current user: root # Current user: uid=0(root) gid=0(root) groups=0(root)
在这种情况下,最简单的解决方案是使用用户名为感兴趣的tilde expansion,结合eval(这是必需的,因为用户名必须作为无引号文字为了波浪号展开工作):
eval echo "~$different_user" # prints $different_user's home dir.
注:通常caveats regarding the use of eval
适用;在这种情况下,假设您控制$ different_user的值,并且知道它是一个纯粹的用户名。
相比之下,本回答的其余部分涉及冒充用户并在该用户的主目录中执行操作。
注意:
>默认情况下管理员和其他用户(如果通过sudoers文件授权)可以通过sudo模拟其他用户。
>以下是基于sudo的默认配置 – 更改其配置可以使它的行为不同 – 请参阅man sudoers。
作为另一个用户执行命令的基本形式是:
sudo -H -u someUser someExe [arg1 ...] # Example: sudo -H -u root env # print the root user's environment
注意:
>如果您忽略指定-H,模拟进程(在指定用户的上下文中调用的进程)将在$ HOME中报告原始用户的主目录。
>模拟进程将具有与调用进程相同的工作目录。
>模拟过程对作为参数传递的字符串文字不执行shell扩展,因为在模拟过程中没有涉及shell(除非someExe恰好是一个shell) – 在传递给模拟过程之前,调用shell的扩展可以很明显仍然发生。
可选地,您可以通过或通过(n模拟)shell运行模拟进程,方法是将someExe前缀为-i或-s – 不指定someExe …创建一个交互式shell:
> -i为someUser创建一个登录shell,这意味着以下内容:
> someUser的用户特定shell配置文件(如果已定义)将被加载。
> $ HOME指向someUser的主目录,所以没有必要-H(虽然你仍然可以指定它)
>模拟shell的工作目录是someUser的主目录。
> -s创建一个非登录shell:
>没有加载shell配置文件(虽然交互式非登录shell的初始化文件是例如〜/ .bashrc)
>除非您也指定-H,否则模拟进程将在$ HOME中报告原始用户的主目录。
>模拟的shell将具有与调用进程相同的工作目录。
使用shell意味着在命令行上传递的字符串参数可能受到模拟shell(可能在调用shell初始扩展之后)的shell扩展 – 见下面的平台特定的区别。比较以下两个命令(使用单引号防止调用shell过早扩展):
# Run root's shell profile,change to root's home dir. sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD' # Don't run root's shell profile,use current working dir. # Note the required -H to define $HOME as root`s home dir. sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'
调用的shell由“SHELL环境变量(如果已设置)或shell在passwd(5)中指定”(根据man sudo)确定。注意,使用-s它是调用用户的环境很重要,而-i它是被模拟的用户的。
请注意,有关shell相关行为(使用-i或-s)的平台差异:
> sudo on Linux显然只接受一个可执行文件或内建名称作为-s / -i之后的第一个参数,而OSX允许传递整个shell命令行;例如,OSX直接接受sudo -u root -s’echo $ SHELL – $ USER – $ HOME – $ PWD'(不需要eval),而Linux不(从sudo 1.8.95p开始)。
> Linux上的旧版本的sudo不会将shell扩展应用于传递给shell的参数;例如,使用sudo 1.8.3p1(例如,Ubuntu 12.04),sudo -u root -H -s echo’$ HOME’只是回显字符串文字“$ HOME”,而不是在root用户的上下文中扩展变量引用。至少sudo 1.8.9p5(例如,Ubuntu 14.04),这已经修复。因此,为了确保在Linux上扩展,即使使用较旧的sudo版本,也可以将整个命令作为单个参数传递给eval;例如:sudo -u root -H -s eval’echo $ HOME’。 (虽然在OSX上不是必需的,但也可以在那里工作。)
> root用户的$ SHELL变量在OSX 10.9上包含/ bin / sh,而在Ubuntu 12.04上是/ bin / bash。
无论模拟进程是否涉及shell,其环境都将设置以下变量,反映调用的用户和命令:SUDO_COMMAND,SUDO_USER,SUDO_UID =,SUDO_GID。
看到人sudo和人sudoers更多的微妙。
提示帽子@DavidW和@Andrew的灵感。