Przekaż funkcję i zmienne do sudo su - <użytkownik> << EOF

9

Zadeklarowałem funkcje i zmienne w bash / ksh i muszę je przekazać do 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
źródło

Odpowiedzi:

4

sudo su -, który jest skomplikowanym sposobem pisania sudo -i, tworzy nieskazitelne środowisko. To jest punkt powłoki logowania. Nawet zwykły sudousuwa większość zmiennych ze środowiska. Ponadto sudojest to polecenie zewnętrzne; nie ma możliwości podniesienia uprawnień w samym skrypcie powłoki, wystarczy uruchomić program zewnętrzny ( sudo) z dodatkowymi uprawnieniami, a to oznacza, że ​​wszelkie zmienne powłoki (tj. zmienne nieeksportowane) i funkcje zdefiniowane w powłoce nadrzędnej nie będą dostępne w skorupa dziecka.

Możesz przepuszczać zmienne środowiskowe, nie wywołując powłoki logowania ( sudo bashzamiast sudo su -lub sudo -i) i konfigurując sudo, aby przepuszczały te zmienne (z Defaults !env_resetlub Defaults env_keep=…w sudoerspliku). To nie pomoże ci w funkcjach (chociaż bash ma funkcję eksportu funkcji, sudo ją blokuje).

Normalnym sposobem na umieszczenie funkcji w powłoce podrzędnej byłoby zdefiniowanie ich tam. Zadbaj o cytowanie: jeśli używasz <<EOFdla dokumentu tutaj, treść dokumentu tutaj jest najpierw rozszerzana przez powłokę nadrzędną, a wynikiem tego rozszerzenia jest skrypt widziany przez powłokę podrzędną. To znaczy, jeśli napiszesz

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

wyświetla nazwę pierwotnego użytkownika, a nie docelowego użytkownika. Aby uniknąć tej pierwszej fazy ekspansji, podaj <<operator znacznika dokumentu tutaj :

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

Jeśli więc nie musisz przekazywać danych z powłoki nadrzędnej do powłoki podrzędnej, możesz użyć cytowanego tutaj dokumentu:

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

Chociaż możesz użyć nie cytowanego tutaj znacznika dokumentu, aby przekazać dane z powłoki nadrzędnej do powłoki podrzędnej, działa to tylko wtedy, gdy dane nie zawierają żadnego znaku specjalnego. To dlatego, że w skrypcie jak

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

wyjście whoamistaje się trochę kodem powłoki, a nie łańcuchem. Na przykład, jeśli whoamipolecenie zwróciło, "; rm -rf /; "truewówczas powłoka potomna wykona polecenie echo ""; rm -rf /; "true".

Jeśli potrzebujesz przekazać dane z powłoki nadrzędnej, prostym sposobem jest przekazanie ich jako argumentów. Wywołaj jawnie powłokę potomną i przekaż jej parametry pozycyjne:

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

Jeśli masz wiele zmiennych do przekazania, łatwiej będzie je przekazać według nazwy. Wywołaj envjawnie, aby ustawić zmienne środowiskowe dla powłoki potomnej.

#!/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

Pamiętaj, że jeśli spodziewałeś się, /etc/profileże użytkownik docelowy ~/.profilezostanie przeczytany, będziesz musiał przeczytać je jawnie lub zadzwonić bash --loginzamiast sh.

Gilles „SO- przestań być zły”
źródło
1

To nie działa, ponieważ funkcja log_fnie jest zadeklarowana w sudo su -uruchamianej powłoce. Zamiast:

extVAR="yourName"

sudo su - <user> << EOF

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

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

Musisz uzyskać funkcję zdefiniowaną w podpowłoce głównej. Może to zrobić, ale .... Nie wiem, co robi większość tych rzeczy. Przynajmniej - o ile ani sudonie supotrzebuje standardowego odczytu hasła - to powinno zostać log_f()zadeklarowane.

Nawiasem mówiąc, ufam, że masz zamiar rozszerzyć te wartości na dane wejściowe powłoki roota. Jeśli nie chcesz tego zrobić, powinieneś zacytować EOFi samych vars.

mikeserv
źródło
1

W moim przypadku musiałem przekazać tablicę i miałem pewne problemy, ale po pewnym czasie odniosłem sukces, wysyłając echo wartości tablicy do envklawisza i zawijając zamierzony kod bash -c '<intended code>', i w zasadzie kazałem jej odtworzyć tablicę, np INNER_KEY=($<env_key>).:

Na przykład:

#!/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

Problem polegał na tym, że nie mogłem bezpośrednio zrobić czegoś takiego (nie używając bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
johanmynhardt
źródło