我尝试导出该函数,然后使用bash执行,但这不起作用:
$ export -f my_func $ sudo bash -c 'my_func' bash: my_func: command not found
如果我尝试使用没有sudo(bash -c’my_func’)的bash运行该函数,它将工作。
任何想法?
从
bmargulies的答案开始,我写了一个功能来解决这个问题,基本上实现了他的想法。
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # EXESUDO # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # # Purpose: # -------------------------------------------------------------------- # # Execute a function with sudo # # Params: # -------------------------------------------------------------------- # # $1: string: name of the function to be executed with sudo # # Usage: # -------------------------------------------------------------------- # # exesudo "funcname" followed by any param # # -------------------------------------------------------------------- # # Created 01 September 2012 Last Modified 02 September 2012 function exesudo () { ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## # # LOCAL VARIABLES: # ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## # # I use underscores to remember it's been passed local _funcname_="$1" local params=( "$@" ) ## array containing all params passed here local tmpfile="/dev/shm/$RANDOM" ## temporary file local filecontent ## content of the temporary file local regex ## regular expression local func ## function source ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## # # MAIN CODE: # ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## # # WORKING ON PARAMS: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Shift the first param (which is the name of the function) unset params[0] ## remove first element # params=( "${params[@]}" ) ## repack array # # WORKING ON THE TEMPORARY FILE: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ content="#!/bin/bash\n\n" # # Write the params array content="${content}params=(\n" regex="\s+" for param in "${params[@]}" do if [[ "$param" =~ $regex ]] then content="${content}\t\"${param}\"\n" else content="${content}\t${param}\n" fi done content="$content)\n" echo -e "$content" > "$tmpfile" # # Append the function source echo "#$( type "$_funcname_" )" >> "$tmpfile" # # Append the call to the function echo -e "\n$_funcname_ \"\${params[@]}\"\n" >> "$tmpfile" # # DONE: EXECUTE THE TEMPORARY FILE WITH SUDO # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sudo bash "$tmpfile" rm "$tmpfile" }
使用示例:
运行以下代码段
#!/bin/bash function exesudo () { # copy here the prevIoUs exesudo function !!! } test_it_out () { local params=( "$@" ) echo "Hello "$( whoami )"!" echo "You passed the following params:" printf "%s\n" "${params[@]}" ## print array } echo "1. calling without sudo" test_it_out "first" "second" echo "" echo "2. calling with sudo" exesudo test_it_out -n "john done" -s "done" exit
会输出
calling without sudo
Hello yourname!
You passed the following params:
first
secondcalling with sudo
Hello root!
You passed the following params:
-n
john done
-s
foo
如果你需要在一个shell中调用一个bashrc中定义的函数,那么另外一个用户在serverfault上提到一个类似的问题,那么你必须将以前的exesudo函数放在同一个bashrc文件上,就像以下:
function yourfunc () { echo "Hello "$( whoami )"!" } export -f yourfunc function exesudo () { # copy here } export -f exesudo
然后你必须注销并重新登录或使用
source ~/.bashrc
最后你可以使用exesudo如下:
$ yourfunc Hello yourname! $ exesudo yourfunc Hello root!