Подтвердить что ты не робот

Как я могу выполнить функцию bash, используя sudo?

Я попытался экспортировать функцию и затем выполнить ее с помощью bash, но это не работает:

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

Если я пытаюсь запустить функцию с помощью bash без sudo (bash -c 'my_func'), она работает.

Любая идея?

4b9b3361

Ответ 1

Начиная с ответа bmargulies, я написал функцию для освещения этой проблемы, которая в основном реализует его идею.

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



Пример использования:
запуск следующего фрагмента

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



Выведет

  • вызов без sudo
    Привет, ваше имя! Вы передали следующие параметры:
    первый
    вторая

  • вызов с sudo
    Hello root!
    Вы передали следующие параметры:
    -n
    john done
    -s
    Foo



Если вам нужно использовать это в оболочке, вызывающей функцию, определенную в вашем bashrc, как задано другим вопросом на serverfault другим пользователем, то у вас есть для размещения предыдущей функции exesudo в том же файле bashrc, как показано ниже:

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

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



Затем вам нужно снова выйти и войти в систему или использовать

source ~/.bashrc



Наконец, вы можете использовать exesudo следующим образом:

$ yourfunc
Hello yourname!

$ exesudo yourfunc
Hello root!

Ответ 2

Каждый раз, когда вы запускаете sudo, он создает forks и запускает новую копию оболочки, работающую от имени root. Эта оболочка не наследует функции из вашей оболочки (она не может) и не наследует функции от предыдущих исполнений. Вам нужно будет записать файл, содержащий определение функции и вызов, и sudo вызов этого.

Ответ 3

Вы можете сделать это с помощью declare -f, как в следующем примере:

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

myfunc foo
DECL='declare -f myfunc'

sudo bash -c "$DECL; myfunc bar"

Ответ 4

Альтернативой вызова вашей функции с помощью sudo является просто перемещение вызовов "sudo" внутри вашей функции. Например, я хотел настроить функцию быстрого доступа в OS X для пересылки localhost на конкретный порт.

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

Функция набирает sudo и запрашивает мой пароль. (Затем нажимает "y" на подсказку для ipfw, не связанного с этим вопросом). После этого sudo кэшируется, поэтому остальная часть функции выполняется без необходимости вводить пароль.

По существу, это просто работает, как:

portforward 8000
Password:
Forwarding localhost to port 8000!

И заполняет мою потребность, потому что мне нужно только один раз ввести пароль и позаботиться о нем. Хотя это немного уродливо, если вы не ввели пароль в первый раз. Дополнительные точки для определения того, удалось ли выполнить первое sudo и выйти из функции, если нет.

Ответ 5

Для коротких и простых вещей, в которых нет одиночных кавычек, это работает для меня:

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

whoAmI
'
sudo bash -c "$code"

# output: root

Ответ 6

Все, что вам нужно сделать, это проверить, является ли вы root, если да, запустите функцию, если нет, вызовите script с помощью sudo:

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

Ответ 7

Если ваша функция в вашем .bashrc

Тогда просто сделайте sudo -i myfunc