为什么“sudo -i”会破坏变量扩展,而无需“-i”也能工作?

Rom*_*Can 7 shell bash sudo

这正如我所期望的那样工作:

$ 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)

Kus*_*nda 8

当您使用-iwith时sudo,将使用用户的登录 shell ,$SHELL并将作为登录 shell 进行调用。

\n

当您另外向该命令提供要运行的命令时,如

\n
sudo -u user -i \'some-command\'\n
Run Code Online (Sandbox Code Playgroud)\n

...sudo将使用 运行该命令$SHELL -c,这意味着它需要将其获取的参数列表转换为单个命令行字符串,该字符串再次由 shell 求值。为此,它必须转义 中的每个字符(some-command字母数字、下划线、连字符和美元符号除外)。

\n

这意味着

\n
sudo -u user -i bash -c \'a="b" ; echo ${a}\'\n
Run Code Online (Sandbox Code Playgroud)\n

将以用户身份执行user,转义为相当于

\n
$SHELL -c bash\\ -c\\ \\\'a\\=\\"b\\"\\ \\;\\ echo\\ $\\{a\\}\\\'\n
Run Code Online (Sandbox Code Playgroud)\n

...使用时$a将命令变成

\n
$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 -cshell 会看到${a}并可以扩展它。

\n

sudo手册中描述选项的部分对此进行了解释-i

\n
-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