我怎样才能用sudo执行一个bash函数?

我有一个全局bashrc中定义的bash函数,它需要root权限才能工作。 我怎样才能与sudo运行,例如sudo myfunction 。 默认情况下会出现错误:

sudo:myfunction:命令未find

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的方法可能会更好地处理这个问题。

你可以export你的函数,使之可用于你想用的bash -c子shell或脚本。

 your_function () { echo 'Hello, World'; } export -f your_function bash -c 'your_function' 

编辑

这适用于直接subhells,但显然sudo不转发函数(只有variables)。 即使使用setenvenv_keep和否定env_reset各种组合似乎没有帮助。

编辑2

但是su 似乎支持导出的函数。

 your_function () { echo 'Hello, World'; } export -f your_function su -c 'your_function' 

也许你可以这样做:

 function meh() { sudo -v sudo cat /etc/shadow } 

这应该工作,并保存你在命令行上键入sudo。

我会执行一个新的shell,让sudo执行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行做一个别名。

 #!/bin/bash function smth() { echo "{{" whoami echo "}}" } if [ $(whoami) != "root" ]; then whoami echo "i'm not root" sudo $0 else smth fi 

正如Legolas在丹尼斯·威廉姆森 ( Dennis Williamson)的回答中所指出的那样,你应该阅读关于在计算器上发布的类似问题的bmargulies的答案。

从此我写了一个函数来解决这个问题,基本上实现了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 

会输出

  1. 没有sudo的调用
    你好,你好!
    你通过了以下参数:
    第一
    第二

  2. 用sudo打电话
    你好!
    你通过了以下参数:
    -n
    约翰做完了
    -s
    FOO

如果你需要在一个调用你的bashrc中定义的函数的shell中使用它,那么你必须把以前的exesudo函数放在同一个bashrc文件中,如下所示:

 function yourfunc () { echo "Hello "$( whoami )"!" } export -f yourfunc function exesudo () { # copy here } export -f exesudo 

然后你必须注销并重新login或使用

 source ~/.bashrc 

最后你可以使用exesudo如下:

 $ yourfunc Hello yourname! $ exesudo yourfunc Hello root! 

如果你需要在sudo的上下文中调用一个函数,你需要使用declare

 #!/bin/bash function hello() { echo "Hello, $USER" } sudo su another_user -c "$(declare -f hello); hello"