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
}