这正如我所期望的那样工作:
$ sudo -u romain bash -c 'a="b" ; echo $a'
b
$
Run Code Online (Sandbox Code Playgroud)
但是跟-i
变量没有回显,为什么呢?
$ sudo -iu romain bash -c 'a="b" ; echo $a'
$
Run Code Online (Sandbox Code Playgroud)
我想知道是否-i
添加了一定程度的 bash 间接或变量插值,但如果是,这如何工作?
$ sudo -iu romain bash -c 'a="b" ; echo ${a}'
b
$
Run Code Online (Sandbox Code Playgroud)
当您使用-i
with时sudo
,将使用用户的登录 shell ,$SHELL
并将作为登录 shell 进行调用。
当您另外向该命令提供要运行的命令时,如
\nsudo -u user -i \'some-command\'\n
Run Code Online (Sandbox Code Playgroud)\n...sudo
将使用 运行该命令$SHELL -c
,这意味着它需要将其获取的参数列表转换为单个命令行字符串,该字符串再次由 shell 求值。为此,它必须转义 中的每个字符(some-command
字母数字、下划线、连字符和美元符号除外)。
这意味着
\nsudo -u user -i bash -c \'a="b" ; echo ${a}\'\n
Run Code Online (Sandbox Code Playgroud)\n将以用户身份执行user
,转义为相当于
$SHELL -c bash\\ -c\\ \\\'a\\=\\"b\\"\\ \\;\\ echo\\ $\\{a\\}\\\'\n
Run Code Online (Sandbox Code Playgroud)\n...使用时$a
将命令变成
$SHELL -c bash\\ -c\\ \\\'a\\=\\"b\\"\\ \\;\\ echo\\ $a\\\'\n
Run Code Online (Sandbox Code Playgroud)\n请注意,在最后一个命令中,$a
在启动之前由用户的登录 shell 展开bash -c
。在前面的命令中,${a}
使用了 where ,$\\{a\\}
不是有效的扩展,因此用户的 shell 不会进行扩展,而内联bash -c
shell 会看到${a}
并可以扩展它。
sudo
手册中描述选项的部分对此进行了解释-i
:
-i, --login\n Run the shell specified by the target user\'s password\n database entry as a login shell. This means that login-\n specific resource files such as .profile, .bash_profile, or\n .login will be read by the shell. If a command is specified,\n it is passed to the shell as a simple command using the -c\n option. The command and any arguments are concatenated,\n separated by spaces, after escaping each character (including\n white space) with a backslash (\xe2\x80\x98\\\xe2\x80\x99) except for alphanumerics,\n underscores, hyphens, and dollar signs. If no command is\n specified, an interactive shell is executed. [...]\n
Run Code Online (Sandbox Code Playgroud)\n