Odpowiedzi:
sudo su -
, który jest skomplikowanym sposobem pisania sudo -i
, tworzy nieskazitelne środowisko. To jest punkt powłoki logowania. Nawet zwykły sudo
usuwa większość zmiennych ze środowiska. Ponadto sudo
jest 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 bash
zamiast sudo su -
lub sudo -i
) i konfigurując sudo, aby przepuszczały te zmienne (z Defaults !env_reset
lub Defaults env_keep=…
w sudoers
pliku). 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 <<EOF
dla 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 whoami
staje się trochę kodem powłoki, a nie łańcuchem. Na przykład, jeśli whoami
polecenie zwróciło, "; rm -rf /; "true
wó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 env
jawnie, 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 ~/.profile
zostanie przeczytany, będziesz musiał przeczytać je jawnie lub zadzwonić bash --login
zamiast sh
.
To nie działa, ponieważ funkcja log_f
nie 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 sudo
nie su
potrzebuje 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ć EOF
i samych vars.
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 env
klawisza 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[@]};
...