How can I execute a bash function using sudo?

后端 未结 7 1280
终归单人心
终归单人心 2020-12-03 01:23

I tried exporting the function and then executing it with bash, but that doesn\'t work:

$ export -f my_func
$ sudo bash -c \'my_func\' 
bash: my_func: comma         


        
相关标签:
7条回答
  • 2020-12-03 01:39

    You can do that using declare -f, as in the following example:

    function myfunc() {
        whoami
        echo First parameter is $1
    }
    
    myfunc foo
    DECL=`declare -f myfunc`
    
    sudo bash -c "$DECL; myfunc bar"
    
    0 讨论(0)
  • 2020-12-03 01:41

    All you have to do is check if you are root, if yes, run the function, if not, call the script with sudo:

    #!/bin/bash
    # script name: 'foo.sh'
    
    function foo(){
        whoami
    }
    
    DIR=$( cd "$( dirname "$0" )" && pwd )   # get script dir
    if [ "$UID" -ne 0 ]; then                # check if you are root
        sudo $DIR/foo.sh                     # NOT: run script with sudo
    else
        foo                                  # YES: run function
    fi
    
    0 讨论(0)
  • 2020-12-03 01:44

    For short and simple stuff that doesn't have single quotes in it, this works for me:

    export code='
    function whoAmI() {
        echo `whoami`
    }
    
    whoAmI
    '
    sudo bash -c "$code"
    
    # output: root
    
    0 讨论(0)
  • 2020-12-03 01:46

    Each time you run sudo, it forks and execs a new copy of the shell, running as root. That shell does not inherit functions from your shell (it can't) and it doesn't inherit functions from previous executions. You will have to write out a file containing the function definition and invocation and sudo the invocation of that.

    0 讨论(0)
  • 2020-12-03 01:51

    If your function is in your .bashrc

    Then just do sudo -i myfunc

    0 讨论(0)
  • 2020-12-03 01:52

    Starting from the answer of bmargulies, I wrote a function to cover this issue, which basically realizes his idea.

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
    # 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 content                       ## content of the temporary file
        local regex                         ## regular expression
        
        
        ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
        #
        # 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"
    }
    



    Example of usage:
    running the following snippet

    #!/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
    



    Will output

    1. calling without sudo
      Hello yourname!
      You passed the following params:
      first
      second

    2. calling with sudo
      Hello root!
      You passed the following params:
      -n
      john done
      -s
      foo



    If you need to use this in a shell calling a function which is defined in your bashrc, as asked with a similar question on serverfault by another user, then you have to put the previous exesudo function on the same bashrc file as well, like the following:

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



    Then you have to logout and login again or use

    source ~/.bashrc
    



    Finally you can use exesudo as follow:

    $ yourfunc
    Hello yourname!
    
    $ exesudo yourfunc
    Hello root!
    
    0 讨论(0)
提交回复
热议问题