Ответы:
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.
Это не работает, потому что функция 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и сами переменные.
В моем случае мне нужно передать массив в и имел некоторые проблемы, но имел успех через некоторое время на вторя ценности буев к 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[@]};
...