我在全局 bashrc 中定义了一个 bash 函数,该函数需要 root 权限才能运行。如何使用 sudo 来运行它,例如sudo myfunction
。默认情况下,它会给出一个错误:
sudo:myfunction:未找到命令
答案1
Luca 好心地向我指出了这个问题,这是我的方法:在调用 sudo 之前展开函数/别名,并将其全部传递给 sudo,不需要临时文件。
解释在我的博客上。有很多引用处理 :-)
# Wrap sudo to handle aliases and functions
# [email protected]
#
# Accepts -x as well as regular sudo options: this expands variables as you not root
#
# Comments and improvements welcome
#
# Installing: source this from your .bashrc and set alias sudo=sudowrap
# You can also wrap it in a script that changes your terminal color, like so:
# function setclr() {
# local t=0
# SetTerminalStyle $1
# shift
# "$@"
# t=$?
# SetTerminalStyle default
# return $t
# }
# alias sudo="setclr sudo sudowrap"
# If SetTerminalStyle is a program that interfaces with your terminal to set its
# color.
# Note: This script only handles one layer of aliases/functions.
# If you prefer to call this function sudo, uncomment the following
# line which will make sure it can be called that
#typeset -f sudo >/dev/null && unset sudo
sudowrap ()
{
local c="" t="" parse=""
local -a opt
#parse sudo args
OPTIND=1
i=0
while getopts xVhlLvkKsHPSb:p:c:a:u: t; do
if [ "$t" = x ]; then
parse=true
else
opt[$i]="-$t"
let i++
if [ "$OPTARG" ]; then
opt[$i]="$OPTARG"
let i++
fi
fi
done
shift $(( $OPTIND - 1 ))
if [ $# -ge 1 ]; then
c="$1";
shift;
case $(type -t "$c") in
"")
echo No such command "$c"
return 127
;;
alias)
c="$(type "$c")"
# Strip "... is aliased to `...'"
c="${c#*\`}"
c="${c%\'}"
;;
function)
c="$(type "$c")"
# Strip first line
c="${c#* is a function}"
c="$c;\"$c\""
;;
*)
c="\"$c\""
;;
esac
if [ -n "$parse" ]; then
# Quote the rest once, so it gets processed by bash.
# Done this way so variables can get expanded.
while [ -n "$1" ]; do
c="$c \"$1\""
shift
done
else
# Otherwise, quote the arguments. The echo gets an extra
# space to prevent echo from parsing arguments like -n
while [ -n "$1" ]; do
t="${1//\'/\'\\\'\'}"
c="$c '$t'"
shift
done
fi
echo sudo "${opt[@]}" -- bash -xvc \""$c"\" >&2
command sudo "${opt[@]}" bash -xvc "$c"
else
echo sudo "${opt[@]}" >&2
command sudo "${opt[@]}"
fi
}
# Allow sudowrap to be used in subshells
export -f sudowrap
这种方法的一个缺点是它只扩展了你调用的函数,而不是你从那里引用的任何额外函数。如果你引用了在 bashrc 中加载的函数(前提是它在调用时执行bash -c
), Kyle 的方法可能处理得更好。
答案2
您可以使export
您的函数可用于bash -c
您想要使用它的子 shell 或脚本。
your_function () { echo 'Hello, World'; }
export -f your_function
bash -c 'your_function'
编辑
这适用于直接子 shell,但显然sudo
不能转发函数(只能转发变量)。即使使用setenv
、env_keep
和否定的各种组合env_reset
似乎也无济于事。
编辑2
然而, 看起来su
做支持导出函数。
your_function () { echo 'Hello, World'; }
export -f your_function
su -c 'your_function'
答案3
如果您需要在 sudo 上下文中调用函数,您需要使用declare
:
#!/bin/bash
function hello() {
echo "Hello, $USER"
}
sudo su another_user -c "$(declare -f hello); hello"
答案4
我将通过让 sudo 执行 shell 本身来执行一个新的 shell,然后该函数将以 root 权限运行。例如:
vim myFunction
#The following three lines go in myFunction file
function mywho {
sudo whoami
}
sudo bash -c '. /home/kbrandt/myFunction; mywho'
root
您甚至可以为该线路创建一个别名sudo bash
。