A partir de la respuesta de bmargulies, escribí una función para cubrir este problema, que básicamente se da cuenta de su 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=("[email protected]") ## 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"
}
Ejemplo de uso:
ejecutando el siguiente fragmento de
#!/bin/bash
function exesudo()
{
# copy here the previous exesudo function !!!
}
test_it_out()
{
local params=("[email protected]")
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
salida Will
llamadas sin sudo
Hola, tu nombre!
usted pasó los siguientes parametros:
primera
segundo
llamando con sudo
Hola raíz!
usted pasó los siguientes parametros:
-n
John Donne
-s
foo
Si necesita utilizar esto en una cáscara de llamar a una función que es definido en su bashrc, como se le preguntó con una pregunta similar en serverfault por otro usuario, entonces usted tiene que poner la función exesudo anterior en el mismo bashrc archivo, así, como la siguiente:
function yourfunc()
{
echo "Hello "$(whoami)"!"
}
export -f yourfunc
function exesudo()
{
# copy here
}
export -f exesudo
entonces usted tiene que iniciar sesión otra vez o utilizar
source ~/.bashrc
Finalmente, puede utilizar exesudo de la siguiente manera:
$ yourfunc
Hello yourname!
$ exesudo yourfunc
Hello root!
Por qué necesita para funcionar de esa manera? –
Porque toda la secuencia de comandos se canaliza a bash a través de stdin. Puede venir de curl, o cat, .. – Miroslav
La misma pregunta en SF: http://serverfault.com/questions/177699/how-can-i-execute-a-bash-function-with-sudo/ –