Переслать функцию и переменные в sudo su - <пользователь> << EOF

9

Я объявил функции и переменные в bash / ksh, и мне нужно перенаправить их в sudo su - {user} << EOF:

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF
waldauf
источник

Ответы:

4

sudo su -, который является сложным способом написания sudo -i, создает нетронутую среду. В этом смысл оболочки входа в систему. Даже равнина sudoудаляет большинство переменных из среды. Кроме того sudo, это внешняя команда; нет никакого способа повысить привилегии в самом сценарии оболочки, только запустить внешнюю программу ( sudo) с дополнительными привилегиями, и это означает, что любые переменные оболочки (то есть неэкспортируемые переменные) и функции, определенные в родительской оболочке, не будут доступны в детская оболочка.

Вы можете передавать переменные окружения, не вызывая оболочку входа ( sudo bashвместо sudo su -или sudo -i) и настраивая sudo для пропуска этих переменных (с файлом Defaults !env_resetили Defaults env_keep=…в sudoersфайле). Это не поможет вам для функций (хотя bash имеет функцию экспорта функций, sudo блокирует ее).

Обычный способ поместить ваши функции в дочернюю оболочку - определить их там. Позаботьтесь о цитировании: если вы используете <<EOFдокумент здесь, содержимое документа здесь сначала раскрывается родительской оболочкой, а результатом этого расширения становится скрипт, который видит дочерняя оболочка. То есть если ты пишешь

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

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

sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF

Поэтому, если вам не нужно передавать данные из родительской оболочки в дочернюю оболочку, вы можете использовать приведенный здесь документ:

#!/bin/bash
sudo -u "$target_user" -i  <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

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

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

вывод whoamiстановится немного кода оболочки, а не строки. Например, если whoamiкоманда вернулась, "; rm -rf /; "trueдочерняя оболочка выполнит команду echo ""; rm -rf /; "true".

Если вам нужно передать данные из родительской оболочки, простой способ - передать их в качестве аргументов. Вызовите дочернюю оболочку явно и передайте ей позиционные параметры:

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh  _ "$extVAR" <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

Если вам нужно передать несколько переменных, будет удобнее передавать их по имени. Вызов envявно, чтобы установить переменные окружения для дочерней оболочки.

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

Обратите внимание, что если вы ожидали, /etc/profileчто целевой пользователь ~/.profileбудет прочитан, вам придется прочитать их явно или вызвать bash --loginвместо sh.

Жиль "ТАК - перестань быть злым"
источник
1

Это не работает, потому что функция log_fне объявлена ​​в sudo su -оболочке, которую вы запускаете. Вместо:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Вам нужно получить функцию, определенную в корневом подоболочке. Это могло бы сделать это, но ... Я не знаю, что делает большинство этого материала. По крайней мере - до тех пор, пока stdin sudoне suнуждается и не нуждается в чтении пароля - это должно быть log_f()объявлено.

Я верю, что вы имеете в виду, кстати, расширить эти значения во входные данные корневой оболочки. Если вы не хотите этого делать, то вам следует цитировать EOFи сами переменные.

mikeserv
источник
1

В моем случае мне нужно передать массив в и имел некоторые проблемы, но имел успех через некоторое время на вторя ценности буев к env-Key и обертыванию намеченного кода bash -c '<intended code>', и в основном имеет его воссоздание массива, например .: INNER_KEY=($<env_key>).

Например:

#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
  bash -c '
    FOO=($PLUGINS);
    echo values: \[${FOO[@]}\];

    for pl in ${FOO[@]};
      do echo value: $pl;
    done;
  '
EOF

Проблема заключалась в том, что я не мог напрямую сделать что-то вроде следующего (не используя bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
johanmynhardt
источник