![Bash 中的波形符扩展与变量](https://linux22.com/image/200333/Bash%20%E4%B8%AD%E7%9A%84%E6%B3%A2%E5%BD%A2%E7%AC%A6%E6%89%A9%E5%B1%95%E4%B8%8E%E5%8F%98%E9%87%8F.png)
请考虑以下片段:
$ export xx=foo
$ sudo bash -c 'echo $xx ~'
/root
这没关系。我们看不到xx。
但是,如果我暴露它:
$ sudo -E bash -c 'echo $xx ~'
foo /home/xropi
虽然很多人说〜不是别名,不知何故它是环境的一部分,因为-E将暴露原件,阻止我推迟其评估。
是否可以在 sudo-ed 命令中传递我的变量并将 ~ 评估为 /root ?
我想在使用 sudo 运行时得到这个:
foo /root
答案1
您对波形符如何工作的理解并不完整。查看man bash
并搜索Tilde Expansion
.
它开头为(额外的换行符和我添加的一些粗体):
如果单词以不带引号的波形符 (
~
) 开头,则第一个不带引号的斜杠之前的所有字符(或所有字符,如果没有不带引号的斜杠)都被视为波形符前缀。如果波形符前缀中的任何字符均未加引号,则波形符前缀中跟随波形符的字符将被视为可能的登录名。
如果此登录名是空字符串,则波浪号将替换为 shell 参数的值
HOME
。 如果HOME
未设置,执行 shell 的用户的主目录将被替换。否则,波形符前缀将替换为与指定登录名关联的主目录。
简而言之,~
如果 $HOME 非空,则扩展为 $HOME。
sudo
在$HOME
没有-E
.有了-E
,确实如此。
顺便说一句,还值得注意的是:虽然大多数 shell 可以并且确实扩展~
为用户的主目录,但并非所有程序都这样做。事实上,大多数程序不这样做 - 这并不是他们真正的工作,他们依赖 shell 来执行波浪号、变量和 glob 以及其他扩展前他们看到任何争论。
问题:是否可以在 sudo-ed 命令中传递我的变量并将 ~ 评估为 /root ?
有多种方法,每种方法都有优点和缺点。这里是其中的一些:
unset HOME
跑步前sudo -E
。HOME=/root
运行前设置sudo -E
。例如HOME=/root sudo -E bash -c 'echo $xx ~'
将要与 sudo 共享的变量写入文件。例如,您可以运行
declare -p var1 var2 var3 > /tmp/myvars.sh
并sudo
(不-E
)运行一个 shell 脚本,该source /tmp/myvars.sh
脚本在运行您想要运行的任何内容之前执行此操作sudo
。使用or
env_keep
中的设置- 这允许您定义在运行时始终保留哪些变量,无论有或没有该选项。/etc/sudoers
/etc/sudoers.d/*
sudo
-E
(来自@MichaelHomer)使用
sudo
的-H
选项将 HOME 设置为目标用户的主目录并--preserve-env=xx
告诉 sudo 传递xx
变量(此选项采用逗号分隔的环境变量名称列表)。man sudo
详情请参阅。请注意,并非所有用户都有权保护环境。看man sudoers
。
sudo
请注意,默认情况下不保留环境变量是有充分理由的。有许多环境变量具有严重的安全隐患,并且滥用可能会允许用户或组获得 root(或其他 uid)访问权限,以访问他们不应访问的内容。