Odpowiedzi:
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.
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.
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[@]};
...