Bash: запуск функции как sudo на удаленном хосте?

#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