我有一个脚本可以执行许多不同的操作,其中大多数不需要任何特殊权限。但是,我在函数中包含的一个特定部分需要 root 权限。
我不希望要求整个脚本以 root 身份运行,并且我希望能够从脚本内以 root 权限调用此函数。如有必要,提示输入密码不是问题,因为无论如何它大多是交互式的。但是,当我尝试使用 时sudo functionx
,我得到:
sudo: functionx: command not found
正如我所料,export
没有什么区别。由于多种原因,我希望能够直接在脚本中执行该函数,而不是将其分解并作为单独的脚本执行。
有什么方法可以使我的函数对 sudo “可见”,而无需提取它,找到适当的目录,然后将其作为独立脚本执行?
该函数本身大约有一页长,包含多个字符串,有些是双引号的,有些是单引号的。它还依赖于主脚本中其他地方定义的菜单功能。
我只希望拥有 sudo ANY 的人能够运行该功能,因为它所做的事情之一就是更改密码。
答案1
我承认没有简单、直观的方法可以做到这一点,而且这有点老套。但是,你可以这样做:
function hello()
{
echo "Hello!"
}
# Test that it works.
hello
FUNC=$(declare -f hello)
sudo bash -c "$FUNC; hello"
或者更简单地说:
sudo bash -c "$(declare -f hello); hello"
这个对我有用:
$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)
$ hello
Hello!
$
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Hello!
基本上,declare -f
将返回函数的内容,然后将其传递给bash -c
内联。
如果要从 bash 的外部实例导出所有函数,请更改FUNC=$(declare -f hello)
为FUNC=$(declare -f)
.
编辑
要解决有关引用的评论,请参阅此示例:
$ hello()
> {
> echo "This 'is a' test."
> }
$ declare -f hello
hello ()
{
echo "This 'is a' test."
}
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Password:
This 'is a' test.
答案2
我已经编写了自己的Sudo
bash 函数来执行此操作,它可以调用函数和别名:
function Sudo {
local firstArg=$1
if [ $(type -t $firstArg) = function ]
then
shift && command sudo bash -c "$(declare -f $firstArg);$firstArg $*"
elif [ $(type -t $firstArg) = alias ]
then
alias sudo='\sudo '
eval "sudo $@"
else
command sudo "$@"
fi
}
答案3
“问题”在于sudo
清除环境(除了少数允许的变量)并将某些变量设置为预定义的安全值,以防范安全风险。换句话说,这实际上并不是一个问题。这是一个特点。
例如,如果您设置PATH="/path/to/myevildirectory:$PATH"
或未sudo
将 PATH 设置为预定义值,则任何未指定其运行的所有命令的完整路径名的脚本(即大多数脚本)都会在/path/to/myevildirectory
任何其他目录之前查找。将诸如ls
或或其他常用工具之类的命令grep
放在那里,您就可以轻松地在系统上执行任何您喜欢的操作。
最简单/最好的方法是将函数重写为脚本并将其保存在路径中的某个位置(或在命令sudo
行上指定脚本的完整路径 - 无论如何您都需要这样做,除非sudo
配置为允许您以 root 身份运行任何命令),并使其可执行chmod +x /path/to/scriptname.sh
将 shell 函数重写为脚本就像将函数定义内的命令保存到文件中一样简单(没有function ...
, {
和}
行)。
答案4
您可以组合函数和别名
例子:
function hello_fn() {
echo "Hello!"
}
alias hello='bash -c "$(declare -f hello_fn); hello_fn"'
alias sudo='sudo '
然后sudo hello
工作