Выполнение функции сценария Bash с помощью Sudo

Если какое-либо из устройств межсетевого экрана поддерживает UPnP, вы можете использовать его для настройки переадресации портов. Существует несколько доступных утилит командной строки, которые можно использовать для отправки вызовов UPnP.

Один из таких наборов утилит можно найти здесь: http://people.ds.cam.ac.uk/ssb22/setup/upnp.html
Скорее всего, вам понадобится необходимый модуль python, который можно установить с помощью pip install --user miniupnpc .

Использование очень простое:

./upnp-add-port 22222 22

Это перенаправит порт 22222 на устройстве firwall на порт 22 на вашем компьютере.

Команда upnp-ports должна показать что-то вроде этого:

./upnp-ports
TCP:22222 -> 192.168.0.139:22   upnp-add-port 22222

35
11.03.2016, 21:57
7 ответов

Я признаю, что нет простого, интуитивно понятного способа сделать это, и это немного халтурно. Но вы можете сделать это так:

function hello()
{
    echo "Hello!"
}

# Test that it works.
hello

FUNC=$(declare -f hello)
sudo bash -c "$FUNC; hello"

Или более просто:

sudo bash -c "$(declare -f hello); hello"

Это работает для меня:

$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)
$ hello
Hello!
$
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Hello!

По сути, declare -f вернет содержимое функции, которое вы затем передадите в bash -c inline.

Если вы хотите экспортировать все функции из внешнего экземпляра bash, измените FUNC=$(declare -f hello) на FUNC=$(declare -f).

Редактировать

Чтобы ответить на комментарии о цитировании, посмотрите этот пример:

$ hello()
> {
> echo "This 'is a' test."
> }
$ declare -f hello
hello ()
{
    echo "This 'is a' test."
}
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Password:
This 'is a' test.
28
20.08.2021, 12:11

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

Например, если вы установили PATH="/path/to/myevildirectory:$PATH" и sudo не установил PATH в предопределенное значение, то любой скрипт, не указавший полный путь ко ВСЕМ запускаемым командам (т.е. большинство скриптов), будет искать в /path/to/myevildirectory перед любым другим каталогом. Поместите туда такие команды, как ls или grep или другие распространенные инструменты, и вы сможете легко делать в системе все, что захотите.

Самый простой/лучший способ - переписать функцию в виде скрипта и сохранить его где-нибудь в пути (или указать полный путь к скрипту в командной строке sudo - что вам в любом случае придется сделать, если только sudo не настроен так, чтобы позволить вам выполнять ЛЮБУЮ команду от имени root), и сделать его исполняемым с помощью chmod +x /path/to/scriptname. sh

Переписать функцию оболочки как сценарий так же просто, как сохранить команды внутри определения функции в файл (без function ... , { и } строк).

5
20.08.2021, 12:11

Предполагая, что ваш скрипт либо (а) самодостаточен, либо (б) может находить свои компоненты на основе местоположения (а не запоминать, где находится ваш домашний каталог), вы можете сделать что-то вроде этого:

  • использовать $0 имя пути для скрипта, используя его в команде sudo, и передать опцию, которую скрипт будет проверять, чтобы вызвать обновление пароля. Если вы полагаетесь на поиск сценария по пути (а не просто запускаете ./myscript), вы должны получить абсолютное имя пути в $0.
  • поскольку sudo запускает скрипт, он имеет доступ к нужным ему функциям в скрипте.
  • в верхней части сценария (точнее, после объявления функций) сценарий проверит свой uid и поймет, что он был запущен от имени root пользователя, и, увидев, что у него установлена опция, указывающая ему обновить пароль, пойдет и сделает это.

Сценарии могут повторяться по разным причинам: изменение привилегий - одна из них.

0
20.08.2021, 12:11

Вот вариант ответа Уилла . Он включает в себя дополнительный catпроцесс, но предлагает удобство heredoc. Вкратце это выглядит так:

f () 
{
    echo ok;
}

cat <<EOS | sudo bash
$(declare -f f)
f
EOS

Если вы хотите больше пищи для размышлений, попробуйте это:

#!/bin/bash

f () 
{ 
    x="a b"; 
    menu "$x"; 
    y="difficult thing"; 
    echo "a $y to parse"; 
}

menu () 
{
    [ "$1" == "a b" ] && 
    echo "here's the menu"; 
}

cat <<EOS | sudo bash
$(declare -f f)
$(declare -f menu)
f
EOS

Выход::

here's the menu
a difficult thing to pass

Здесь у нас есть функция menu, соответствующая функции в вопросе, которая «определена в другом месте основного скрипта». Если "в другом месте" означает, что его определение уже было прочитано на этом этапе, когда функция, требующая sudo, выполняется, то ситуация аналогична. Но, возможно, его еще не читали. Может быть другая функция, которая вызовет его определение. В этом случае declare -f menuнужно заменить на что-то более сложное или весь скрипт подправить таким образом, что функция menuуже объявлена.

1
20.08.2021, 12:11

Для этого я написал свою собственную Sudoфункцию bash, она работает для вызова функций и псевдонимов:

function Sudo {
        local firstArg=$1
        if [ $(type -t $firstArg) = function ]
        then
                shift && command sudo bash -c "$(declare -f $firstArg);$firstArg $*"
        elif [ $(type -t $firstArg) = alias ]
        then
                alias sudo='\sudo '
                eval "sudo $@"
        else
                command sudo "$@"
        fi
}
4
20.08.2021, 12:11

Вы можете комбинировать функции и псевдонимы

Пример:

function hello_fn() {
    echo "Hello!" 
}

alias hello='bash -c "$(declare -f hello_fn); hello_fn"' 
alias sudo='sudo '

затем sudo helloработает

2
20.08.2021, 12:11

Новый ответ. Добавьте это в свой ~/.bashrc для запуска функций. В качестве бонуса он также может запускать псевдонимы.

ssudo () # super sudo
{
  [[ "$(type -t $1)" == "function" ]] &&
    ARGS="$@" && sudo bash -c "$(declare -f $1); $ARGS"
}
alias ssudo="ssudo "
1
20.08.2021, 12:11

Теги

Похожие вопросы