A partire dalla risposta di bmargulies, ho scritto una funzione per coprire questo problema, che sostanzialmente realizza la sua 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"
}
Esempio di utilizzo:
eseguendo il seguente frammento
#!/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
uscita sarà
chiamando senza sudo
Ciao yourname!
Hai superato i seguenti: params
primo
secondo
chiamando con sudo
Ciao root!
Hai superato i seguenti: params
-n
John Donne
-s
foo
Se è necessario utilizzare questo in un guscio di chiamata di una funzione che è definito nella tua bascrc, come richiesto con una domanda simile su serverfault da un altro utente, quindi devi mettere la precedente funzione exesudo sullo stesso bashrc file come bene, come il seguente:
function yourfunc()
{
echo "Hello "$(whoami)"!"
}
export -f yourfunc
function exesudo()
{
# copy here
}
export -f exesudo
poi si deve logout e login di nuovo o utilizzare
source ~/.bashrc
Infine è possibile utilizzare exesudo come segue:
$ yourfunc
Hello yourname!
$ exesudo yourfunc
Hello root!
fonte
2012-09-01 18:30:12
Perché è necessario eseguire in questo modo? –
Poiché l'intero script viene convogliato per bash tramite stdin. Potrebbe venire da arricciare, o gatto, .. – Miroslav
La stessa domanda su SF: http://serverfault.com/questions/177699/how-can-i-execute-a-bash-function-with-sudo/ –