我打算为
sudo
命令编写一个 shell 包装器以及 root 帐户的完整登录上下文。如果我使用 sudo
标志调用 -i
命令,我遇到了美元字符消失或解释的问题。
当我执行命令
sudo -n /bin/printf "%s\n" '$a'
时,我得到输出:
$a
当我执行命令
sudo -i -n /bin/printf "%s\n" '$a'
时,我得到一个空行作为输出。
对于第二种情况,我期望得到与第一个命令相同的输出。难道是我的期望错了? 如果是,转义美元字符以匹配第一个命令的输出的适当方法是什么?
man sudo
-i, -‐login
运行目标用户密码指定的shell 数据库条目作为登录 shell。这意味着登录- 特定资源文件,例如
、.profile
或.bash_profile
将被 shell 读取。如果指定了.login
,则通过 使用command
command
选项作为简单的-c
到 shell。任何command
在转义后都被连接起来,并用空格分隔 每个字符(包括空格)都带有反斜杠 (args
) 字母数字、下划线、连字符和美元符号除外。‘\’
因此
sudo /bin/printf "%s\n" '$a'
直接使用两个参数(%s\n
和 $a
)运行 printf,并且 printf 不知道有关 shell 变量的任何信息,因此将它们打印为未展开。
另一方面:
sudo -i /bin/printf "%s\n" '$a'
分叉一个新的 shell(用户的登录 shell),然后传递命令和参数。除字母数字、下划线、连字符和美元符号之外的字符都会被转义。所以你最终会通过 sudo 执行以下命令:
/bin/sh -c '/bin/printf %s\n $a'
。然后 shell 执行命令 /bin/printf %s\n $a
,这意味着它将在将参数传递给 printf 之前扩展该参数。