我有2个变量password =" 123"和filepath ="/dir-1/dir2",两者都以所有用户可见的env vars导出。
我试图回声到属于under1的文件/dir-1/dir2/文件。我知道这个问题是因为Shell重定向无法与Sudo一起使用,即sudo echo <TEXT> >> <FILE>
,所以我所做的是:
sudo bash -c 'echo "MY.Password $PASSWORD" >> ${FILEPATH}/file'
sudo bash -c 'echo MY.Password $PASSWORD >> ${FILEPATH}/file'
我希望看到文件中的最后一行是:
MY.Password 123
但是,尽管该变量被正确替换,但MY.Password 123
的预期内容并未显示为/dir-1/dir2/file
文件中的最后一行。
我尝试了
sudo bash -c "echo My.Password '$PASSWORD' >> ${FILEPATH}/file"
sudo bash -c "echo My.Password $PASSWORD >> ${FILEPATH}/file"
都起作用。
然后,我开始考虑是否是因为单一的报价,我试图用双引号逃脱单语:
sudo bash -c 'echo "'"MY.Password $PASSWORD"'" >> "'"${FILEPATH}"'"/file'
这个奇怪的命令也有效...
谁能解释我为什么我的命令不起作用,以及为什么最后一个奇怪的命令起作用?
sudo
默认情况下不会通过您的环境。sudo
具有一个选项-E
或--preserve-env
,该选项可在sudo
下保留命令内的现有环境。示例:
# let's set some variable `a`
a=Hello
# will print an empty line
sudo sh -c 'echo $a'
# will print Hello
sudo sh -c "echo $a"
# will print an empty line
sudo -E sh -c 'echo $a'
# because first we need to make `a` exported
export a
# this will print Hello
sudo -E sh -c 'echo $a'
当您使用双引号时,扩展会在调用sudo
之前发生。因此,扩展/执行是这样的:
$ sudo sh -c "echo $a"
+ sudo sh -c 'echo Hello'
+ sh -c 'echo Hello'
+ echo Hello
Hello
当您使用单个引号时,扩展/执行如下:
$ sudo sh -c 'echo $a'
+ sh -c 'echo $a'
+ echo $a
# now it depends if `$a` exists here, after `sudo` inside `sh`
+ echo
如果变量不在环境中,它将扩展到一无所有。
sudo bash -c 'echo "MY.Password $PASSWORD" >> ${FILEPATH}/file'
PASSWORD
和FILEPATH
变量未在sudo
内设置,因此它们会扩展到空字符串。
sudo bash -c "echo My.Password '$PASSWORD' >> ${FILEPATH}/file"
首先,您的外壳是PASSWORD
和FILEPATH
变量扩展。然后执行sudo
,然后执行bash
。在bash
内部执行echo My.Password 'PASSWORD' >> FILEPATH/file
,因此可以工作。
sudo bash -c 'echo "'"MY.Password $PASSWORD"'" >> "'"${FILEPATH}"'"/file'
让我们用newlines将其分开:
sudo bash -c 'echo "'
"MY.Password $PASSWORD"
'" >> "'
"${FILEPATH}"
'"/file'
因为您的变量在"
内部,然后在调用sudo之前会扩展。然后,在sudo
内部,它们已经扩展并正确地引用了值,这些值位于子外壳中的"
内。这是"最正确"的形式,因为应该在"
内正确引用扩展的值,以便在EX时没有任何奇怪的情况。FILEPATH
中有一个空间。
我通常这样做:
sudo bash -c 'echo MY.Password "$1" >> "$2"/file' -- "$PASSWORD" "$FILEPATH"
这让我不必担心在外壳内使用"
引号,尽管如此
另外,您可以这样做:
export PASSWORD FILEPATH
sudo -E bash -c 'echo MY.Password "$PASSWORD" >> "$FILEPATH"/file'
或去喝茶:
echo MY.Password "$PASSWORD" | sudo tee -a "$FILEPATH"/file