Frage Wie kann ich eine Bash-Funktion mit Sudo ausführen?


Ich habe versucht, die Funktion zu exportieren und dann mit bash auszuführen, aber das funktioniert nicht:

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

Wenn ich versuche, die Funktion mit bash ohne sudo auszuführen (bash -c 'my_func'), funktioniert es.

Irgendeine Idee?


24
2018-02-25 23:06


Ursprung


Antworten:


Ausgehend von der Antwort von BmarguliesIch habe eine Funktion geschrieben, um dieses Thema zu behandeln, das im Grunde seine Idee verwirklicht.

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
# 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=( "$@" )               ## 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"
}



Anwendungsbeispiel:
das folgende Snippet ausführen

#!/bin/bash

function exesudo ()
{
    # copy here the previous exesudo function !!!
}

test_it_out ()
{
    local params=( "$@" )
    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



Wird ausgegeben

  1. Anrufen ohne Sudo
      Hallo Ihr Name!
      Du hast folgende Params bestanden:
      zuerst
      zweite

  2. mit Sudo anrufen
      Hallo Wurzel!
      Du hast folgende Params bestanden:
      -n
      John fertig
      -s
      foo



Wenn Sie dies in einer Shell verwenden müssen, die eine Funktion aufruft, die in Ihrem bashrc definiert ist, wie mit einer ähnlichen Frage auf gefragt Serverfehler von einem anderen Benutzer, dann müssen Sie die vorherige Exesudo-Funktion auf die gleiche setzen Bashrc Datei wie folgt:

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

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



Dann müssen Sie sich abmelden und erneut anmelden oder verwenden

source ~/.bashrc



Schließlich können Sie exesudo wie folgt verwenden:

$ yourfunc
Hello yourname!

$ exesudo yourfunc
Hello root!

14
2017-09-01 18:30



Jedes Mal, wenn Sie sudo ausführen, verzweigt es und führt eine neue Kopie der Shell aus, die als root ausgeführt wird. Diese Shell erbt keine Funktionen von Ihrer Shell (sie kann nicht) und erbt keine Funktionen von früheren Ausführungen. Sie müssen eine Datei schreiben, die die Funktionsdefinition und den Aufruf enthält, und den Aufruf der Funktion sudo ausführen.


15
2018-02-25 23:12



Sie können das tun mit declare -f, wie im folgenden Beispiel:

function myfunc() {
    whoami
    echo First parameter is $1
}

myfunc foo
DECL=`declare -f myfunc`

sudo bash -c "$DECL; myfunc bar"

10
2017-09-25 10:13



Eine Alternative zum Aufruf Ihrer Funktion mit sudo besteht darin, einfach die "sudo" -Aufrufe innerhalb Ihrer Funktion zu verschieben. Zum Beispiel wollte ich in OS X eine Verknüpfungsfunktion einrichten, um localhost an einen bestimmten Port weiterzuleiten.

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

Die Funktion trifft auf sudo und fragt nach meinem Passwort. (Dann pipes "y" zu einer Eingabeaufforderung für ipfw, nicht im Zusammenhang mit dieser Frage). Danach wird sudo zwischengespeichert, so dass der Rest der Funktion ausgeführt wird, ohne dass ein Passwort eingegeben werden muss.

Im Wesentlichen läuft das einfach wie folgt ab:

portforward 8000
Password:
Forwarding localhost to port 8000!

Und erfüllt mein Bedürfnis, denn ich muss nur einmal das Passwort eingeben und es ist erledigt. Obwohl es ein wenig hässlich ist, wenn Sie das Passwort das erste Mal nicht eingeben. Zusätzliche Punkte, um festzustellen, ob das erste Sudo erfolgreich war und ob die Funktion beendet wurde.


3
2017-10-24 16:23



Für kurze und einfache Sachen, die keine einfachen Anführungszeichen haben, funktioniert das für mich:

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

whoAmI
'
sudo bash -c "$code"

# output: root

1
2018-03-14 12:27



Alles, was Sie tun müssen, ist zu überprüfen, ob Sie root sind, wenn ja, führen Sie die Funktion aus, wenn nicht, rufen Sie das Skript mit sudo auf:

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

function foo(){
    whoami
}

DIR=$( cd "$( dirname "$0" )" && 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