sudo在bash中回声仅使用双引号,但不使用单引号



我有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'

PASSWORDFILEPATH变量未在sudo内设置,因此它们会扩展到空字符串。

sudo bash -c "echo My.Password '$PASSWORD' >> ${FILEPATH}/file"  

首先,您的外壳是PASSWORDFILEPATH变量扩展。然后执行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

最新更新