Функція вперед і змінні в sudo su - <user> << 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

Відповіді:


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

Вам потрібно визначити функцію, визначену в кореневій підзахисті. Це могло б зробити це, але .... я не знаю, чим займається більшість цих речей. Принаймні - до тих пір, поки ні sudoі не suпотрібно stdin, щоб прочитати пароль - це слід log_f()оголосити.

Я вірю, що ви, до речі, маєте намір розширити ці значення на вхід кореневої оболонки. Якщо ви цього не хочете робити, то слід навести EOFі самі вари.


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[@]};
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.