调用 bash 函数作为根,但给出'unexpected end of file'



为什么最后一个例子抛出错误,而其他的工作?Bash在任何情况下都会被调用。

#!/bin/bash
function hello {
echo "Hello! user=$USER, uid=$UID, home=$HOME"; 
}
# Test that it works.
hello
# ok
bash -c "$(declare -f hello); hello"
# ok
sudo su $USER bash -c "$(declare -f hello); hello"
# error: bash: -c: line 1: syntax error: unexpected end of file
sudo -i -u $USER bash -c "$(declare -f hello); hello"

-i--login开关失败:

似乎在调试时使用-x

$ set -x
$ sudo -i -u $USER bash -c "$(declare -f hello); hello"
++ declare -f hello
+ sudo -i -u lea bash -c 'hello () 
{ 
echo "Hello! user=$USER, uid=$UID, home=$HOME"
}; hello'

现在如果手动操作,它会导致相同的错误:

sudo -i -u lea bash -c 'hello () 
{ 
echo "Hello! user=$USER, uid=$UID, home=$HOME"
}; hello'

现在让我们做一个简单的小改变,使它工作:

sudo -i -u lea bash -c 'hello () 
{ 
echo "Hello! user=$USER, uid=$UID, home=$HOME";}; hello'

原因是sudo -i像交互式shell一样运行一切。这样做的时候,每一个换行符从declare -f hello变成内部空间。当在同一行时,花括号代码块在结束花括号前需要一个分号,declare -f funcname没有提供,因为它在新行处用结束花括号展开了函数源。

现在让我们让这个行为变得非常简单:

$ sudo bash -c 'echo hello 
echo world'
hello
world

执行两个echo语句,因为它们由换行符分隔。

但:

$ sudo -i bash -c 'echo hello 
echo world'
hello echo world

它执行第一个echo语句打印一切作为参数,因为换行符已经被空间所取代。

在所有示例中都是相同的代码,所以应该没问题。

是的,"$(declare -f hello); hello"总是相同的字符串。但Lea Gris发现sudo susudo -i的处理方式不同。

sudo -i在传递给bash之前引用了它的参数。这个报价过程似乎没有记录,而且很差。要查看实际执行的内容,可以在~/.bash_profile/中打印传递给bash -c的参数:

~/.bash_profile内容

cat <<EOF
# is executed as
$BASH_EXECUTION_STRING
# resulting in output
EOF

sudo -i的糟糕和不一致引用的一些例子

换行符被换行

$ sudo -u $USER -i echo '1
2'
# is executed as
echo 1
2
# resulting in output
12

引号转义为字面量

$ sudo -u $USER -i echo 'single' "double"
# is executed as
echo 'single' "double"
# resulting in output
'single' "double"

但是$没有被引用

$ sudo -u $USER -i echo $var
# is executed as
echo $var
# resulting in output

附注:

您对su的使用可能存在误解。

sudo su $USER bash -c "some command"

doesnotexecutebash -c "echo 1; echo 2"-c ...su解释,并作为-c ...传递给$USER的默认shell。之后,剩余的参数也传递给该shell。执行的命令为

defaultShellOfUSER -c "some command" bash

你可能想写

sudo su -s bash -c "some command" "$USER"

交互shell的行为不同

su只执行-c指定的命令。但是sudo -i启动了一个登录shell,在您的情况下,登录shell似乎是bash(这并不一定是这种情况,参见上面的章节)。

交互式bash会话的行为与bash -c "..."bash script.sh不同。交互式bash源文件如.profile.bash_profile,并支持历史扩展、别名等。有关完整列表,请参阅bash手册中的交互式Shell行为一节。

相关内容