#bash #function #ssh #sudo
#bash #функция #ssh #sudo
Вопрос:
У меня есть следующий пример сценария для запуска команд на удаленном хосте.
Скрипт принимает пароль удаленного хоста из пользовательского ввода, который мы можем использовать для входа в систему как этот пользователь, и я ожидаю, что он также перейдет к sudo
.
Проблема в том, что я не могу заставить функцию runOnRemoteHostAsRoot работать внутри второй функции для запуска с помощью sudo
, которая мне нужна.
Как мне заставить это работать?
Платформа на обоих концах — Ubuntu 18 или 20.
#!/bin/bash
read SSHPASS
export SSHPASS
runOnRemoteHost() {
# ...
whoami
# ...
}
# ...
sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHost); runOnRemoteHost" 2>amp;1
# ...
runOnRemoteHostAsRoot() {
# ...
whoami
# ...
}
# ...
echo "${SSHPASS}" | sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHostAsRoot); sudo --stdin runOnRemoteHostAsRoot" 2>amp;1
# ...
Ожидаемый результат:
user
root
Фактический результат:
user
[sudo] password for user: sudo: runOnRemoteHostAsRoot: command not found
Комментарии:
1.
sudo
в качестве аргумента требуется имя исполняемого файла, а не функции оболочки.2. Хорошо. Вопрос в том, как мне запускать команды внутри
runOnRemoteHostAsRoot
от имени root на удаленном хосте?3. Примечание: Bash не выполняет лексическую область видимости, поэтому определение вложенной функции каким-либо образом не ограничивает область действия внутренней функции внешней функцией.
4. Вам нужно запустить оболочку от имени root, которая выполняет функцию. Что-то вроде
sudo sh -c "$(typeset -f runOnRemoteHost); runOnRemoteHost"
).typeset
Подобное использование в лучшем случае выглядит хрупким. Просто определите функцию непосредственно в аргументе-c
или, что еще лучше, определите скрипт, который вы сначала копируете на удаленный хост, а затем просто выполняете с помощьюsudo
.5.
sudo sh -c "$(typeset -f runOnRemoteHost); runOnRemoteHost"
результат: bash: -c: строка 0: синтаксическая ошибка около неожиданного токена(' bash: -c: line 0:
sudo sh -c runOnRemoteHost () ‘
Ответ №1:
Предложение от @Will полезно в этом случае, используя sudo bash -c
, затем объявляя и запуская функцию:
sudo bash -c "$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot"
Мы будем использовать эту строку после передачи пароля через sshpass
для входа без пароля, вот так:
echo '${SSHPASS}' | sudo --stdin bash -c '$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot'`
Итак, используя это в приведенном выше примере:
#!/bin/bash
read SSHPASS
export SSHPASS
runOnRemoteHost() {
# ...
whoami
# ...
}
# ...
sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHost); runOnRemoteHost" 2>amp;1
# ...
runOnRemoteHostAsRoot() {
# ...
whoami
# ...
}
# ...
sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "echo '${SSHPASS}' | sudo --stdin bash -c '$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot'" 2>amp;1
Вывод:
user
root