Если какое-либо из устройств межсетевого экрана поддерживает 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
Я признаю, что нет простого, интуитивно понятного способа сделать это, и это немного халтурно. Но вы можете сделать это так:
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.
Проблема" заключается в том, что sudo
очищает окружение (за исключением горстки разрешенных переменных) и устанавливает некоторые переменные в предопределенные безопасные значения, чтобы защитить от рисков безопасности. другими словами, это не проблема. Это функция.
Например, если вы установили PATH="/path/to/myevildirectory:$PATH"
и sudo
не установил PATH в предопределенное значение, то любой скрипт, не указавший полный путь ко ВСЕМ запускаемым командам (т.е. большинство скриптов), будет искать в /path/to/myevildirectory
перед любым другим каталогом. Поместите туда такие команды, как ls
или grep
или другие распространенные инструменты, и вы сможете легко делать в системе все, что захотите.
Самый простой/лучший способ - переписать функцию в виде скрипта и сохранить его где-нибудь в пути (или указать полный путь к скрипту в командной строке sudo
- что вам в любом случае придется сделать, если только sudo
не настроен так, чтобы позволить вам выполнять ЛЮБУЮ команду от имени root), и сделать его исполняемым с помощью chmod +x /path/to/scriptname. sh
Переписать функцию оболочки как сценарий так же просто, как сохранить команды внутри определения функции в файл (без function ...
, {
и }
строк).
Предполагая, что ваш скрипт либо (а) самодостаточен, либо (б) может находить свои компоненты на основе местоположения (а не запоминать, где находится ваш домашний каталог), вы можете сделать что-то вроде этого:
$0
имя пути для скрипта, используя его в команде sudo
, и передать опцию, которую скрипт будет проверять, чтобы вызвать обновление пароля. Если вы полагаетесь на поиск сценария по пути (а не просто запускаете ./myscript
), вы должны получить абсолютное имя пути в $0
. sudo
запускает скрипт, он имеет доступ к нужным ему функциям в скрипте. uid
и поймет, что он был запущен от имени root пользователя, и, увидев, что у него установлена опция, указывающая ему обновить пароль, пойдет и сделает это. Сценарии могут повторяться по разным причинам: изменение привилегий - одна из них.
Вот вариант ответа Уилла . Он включает в себя дополнительный 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
уже объявлена.
Для этого я написал свою собственную 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
}
Вы можете комбинировать функции и псевдонимы
Пример:
function hello_fn() {
echo "Hello!"
}
alias hello='bash -c "$(declare -f hello_fn); hello_fn"'
alias sudo='sudo '
затем sudo hello
работает
Новый ответ. Добавьте это в свой ~/.bashrc для запуска функций. В качестве бонуса он также может запускать псевдонимы.
ssudo () # super sudo
{
[[ "$(type -t $1)" == "function" ]] &&
ARGS="$@" && sudo bash -c "$(declare -f $1); $ARGS"
}
alias ssudo="ssudo "