Executing a Bash Script Function with Sudo

I will admit that there's no simple, intuitive way to do this, and this is a bit hackey. But, you can do it like this:

function hello()
{
    echo "Hello!"
}

# Test that it works.
hello

FUNC=$(declare -f hello)
sudo bash -c "$FUNC; hello"

Or more simply:

sudo bash -c "$(declare -f hello); hello"

It works for me:

$ 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!

Basically, declare -f will return the contents of the function, which you then pass to bash -c inline.

If you want to export all functions from the outer instance of bash, change FUNC=$(declare -f hello) to FUNC=$(declare -f).

Edit

To address the comments about quoting, see this example:

$ 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.

The "problem" is that sudo clears the environment (except for a handful of allowed variables) and sets some variables to pre-defined safe values in order to protect against security risks. in other words, this is not actually a problem. It's a feature.

For example, if you set PATH="/path/to/myevildirectory:$PATH" and sudo didn't set PATH to a pre-defined value then any script that didn't specify the full pathname to ALL commands it runs (i.e. most scripts) would look in /path/to/myevildirectory before any other directory. Put commands like ls or grep or other common tools in there and you can easily do whatever you like on the system.

The easiest / best way is to re-write the function as a script and save it somewhere in the path (or specify the full path to the script on the sudo command line - which you'll need to do anyway unless sudo is configured to allow you to run ANY command as root), and make it executable with chmod +x /path/to/scriptname.sh

Rewriting a shell function as a script is as simple as just saving the commands inside the function definition to a file (without the function ..., { and } lines).


I've written my own Sudo bash function to do that, it works to call functions and aliases :

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
}