Comment puis-je exécuter une fonction bash en utilisant sudo?

j'ai essayé d'exporter la fonction puis de l'exécuter avec bash, mais cela ne fonctionne pas:

$ export -f my_func
$ sudo bash -c 'my_func' 
bash: my_func: command not found

Si j'essaie d'exécuter la fonction avec bash sans sudo (bash -c 'my_func'), il fonctionne.

une idée?

24
demandé sur user1729210 2012-02-26 03:06:38
la source

6 ответов

à partir de la réponse de bmargulies , j'ai écrit une fonction pour couvrir cette question, qui réalise essentiellement son idée.

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
# EXESUDO
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
#
# Purpose:
# -------------------------------------------------------------------- #
# Execute a function with sudo
#
# Params:
# -------------------------------------------------------------------- #
# :   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_=""

    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"
}





Exemple d'utilisation:

exécutant l'extrait suivant

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





Sortie

  1. appel sans sudo

    Bonjour votrenom!

    Vous avez réussi les params suivants:

    premier

    deuxième

  2. appel avec sudo

    Bonjour racine!

    Vous avez réussi les params suivants:

    -n

    jean faire

    -s

    foo





Si vous devez utiliser ceci dans un shell appelant une fonction qui est définie dans votre bashrc, comme demandé avec une question similaire sur serverfault par un autre utilisateur, alors vous devez mettre la fonction exesudo précédente sur la même bashrc fichier en tant que bien, comme le suivant:

function yourfunc ()
{
echo "Hello "$( whoami )"!"
}
export -f yourfunc

function exesudo ()
{
   # copy here
}
export -f exesudo





Ensuite, vous devez vous déconnecter et vous connecter à nouveau ou utiliser

source ~/.bashrc





Enfin, vous pouvez utiliser exesudo comme suit:

$ yourfunc
Hello yourname!

$ exesudo yourfunc
Hello root!
14
répondu Luca Borrione 2017-04-13 15:13:48
la source

chaque fois que vous exécutez sudo, il bifurque et exécute une nouvelle copie du shell, en exécutant root. Ce shell n'hérite pas des fonctions de votre shell (il ne peut pas) et il n'hérite pas des fonctions des exécutions précédentes. Vous devrez écrire un fichier contenant la définition de la fonction et l'invocation et sudo l'invocation de cela.

15
répondu bmargulies 2012-02-26 03:12:50
la source

vous pouvez faire cela en utilisant declare -f , comme dans l'exemple suivant:

function myfunc() {
    whoami
    echo First parameter is 
}

myfunc foo
DECL=`declare -f myfunc`

sudo bash -c "$DECL; myfunc bar"
10
répondu Karatheodory 2018-06-16 14:32:36
la source

une alternative à l'appel de votre fonction avec sudo est de simplement déplacer les appels "sudo" à l'intérieur de votre fonction. Par exemple, je voulais mettre en place une fonction de raccourci dans OS X pour acheminer localhost vers un port particulier.

function portforward() {
    echo "y" | sudo ipfw flush;
    sudo ipfw add 100 fwd 127.0.0.1, tcp from any to any 80 in;
    echo "Forwarding localhost to port !";
}

la fonction hits sudo et demande mon mot de passe. (Puis pipes " y " à un prompt pour ipfw, non lié à cette question). Après cela, sudo est caché de sorte que le reste de la fonction exécute sans la nécessité d'entrer un mot de passe.

essentiellement, cela fonctionne comme:

portforward 8000
Password:
Forwarding localhost to port 8000!

et répond à mon besoin car je n'ai besoin d'entrer le mot de passe qu'une seule fois et c'est réglé. Bien que ce soit un peu moche si vous ne parvenez pas à entrer le mot de passe la première fois. Points supplémentaires pour détecter si le premier sudo a réussi et quitter la fonction si ce n'est pas le cas.

3
répondu timothyashaw 2013-10-24 20:41:59
la source

pour des trucs courts et simples qui n'ont pas de guillemets, ça me va:

export code='
function whoAmI() {
    echo `whoami`
}

whoAmI
'
sudo bash -c "$code"

# output: root
1
répondu Shavais 2013-04-12 05:27:50
la source

tout ce que vous avez à faire est de vérifier si vous êtes root, si oui, lancez la fonction, si non, appelez le script avec sudo:

#!/bin/bash
# script name: 'foo.sh'

function foo(){
    whoami
}

DIR=$( cd "$( dirname ""151900920"" )" && 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
répondu gospes 2014-03-14 16:27:14
la source

Autres questions sur