Funzione forward e variabili in sudo su - <utente> << EOF


9

Ho dichiarato funzioni e variabili in bash / ksh e devo inoltrarle in sudo su - {user} << EOF:

#!/bin/bash

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

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Risposte:


4

sudo su -, che è un modo complicato di scrivere sudo -i, costruisce un ambiente incontaminato. Questo è il punto di una shell di login. Anche un piano sudorimuove la maggior parte delle variabili dall'ambiente. Inoltre sudoè un comando esterno; non c'è modo di elevare i privilegi nello stesso script di shell, solo per eseguire un programma esterno ( sudo) con privilegi extra, e ciò significa che qualsiasi variabile di shell (ovvero variabili non esportate) e le funzioni definite nella shell padre non saranno disponibili in il guscio del bambino.

È possibile passare attraverso le variabili di ambiente non invocando una shell di login ( sudo bashinvece di sudo su -o sudo -i) e configurando sudo per far passare queste variabili (con Defaults !env_reseto Defaults env_keep=…nel sudoersfile). Questo non ti aiuterà per le funzioni (sebbene bash abbia una funzione di esportazione delle funzioni, sudo la blocca).

Il modo normale di ottenere le funzioni nella shell figlio sarebbe definirle lì. Abbi cura di citare: se usi <<EOFper il documento here, il contenuto del documento here viene prima espanso dalla shell genitore e il risultato di tale espansione diventa lo script che vede la shell figlio. Cioè, se scrivi

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

questo visualizza il nome dell'utente originale, non dell'utente di destinazione. Per evitare questa prima fase di espansione, citare il marcatore del documento qui dopo l' <<operatore:

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

Quindi, se non è necessario passare i dati dalla shell padre alla shell figlio, è possibile utilizzare un documento citato qui:

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

Sebbene sia possibile utilizzare un marcatore di documenti qui non quotato per passare i dati dalla shell padre alla shell figlio, questo funziona solo se i dati non contengono alcun carattere speciale. Questo perché in una sceneggiatura simile

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

l'output di whoamidiventa un po 'di codice shell, non una stringa. Ad esempio, se il whoamicomando restituito, "; rm -rf /; "truela shell figlio eseguirà il comando echo ""; rm -rf /; "true".

Se è necessario passare i dati dalla shell padre, un modo semplice è passarli come argomenti. Richiamare esplicitamente la shell figlio e passargli i parametri posizionali:

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

Se hai più variabili da passare, sarà più leggibile passarle per nome. Chiamare envesplicitamente per impostare le variabili di ambiente per la shell figlio.

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

Tieni presente che se ti aspettavi /etc/profileche l'utente di destinazione ~/.profilefosse letto, dovrai leggerli esplicitamente o chiamare bash --logininvece di sh.


1

Questo non funziona perché la funzione log_fnon è dichiarata nella sudo su -shell che si avvia. Anziché:

extVAR="yourName"

sudo su - <user> << EOF

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

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

È necessario ottenere la funzione definita nella subshell radice. Potrebbe farlo, ma .... Non so cosa faccia la maggior parte di quella roba. Almeno - fino a quando non sudone suesigenze stdin di leggere una password - che dovrebbe ottenere log_f()dichiarata.

Confido che intendi espandere quei valori nell'input della shell di root, comunque. Se non intendi farlo, allora dovresti citare EOFe gli stessi.


1

Nel mio caso avevo bisogno di passare un array e ho avuto qualche problema, ma dopo un po 'ho avuto successo riecheggiando i valori dell'array in un env-key e avvolgendo il codice desiderato bash -c '<intended code>', e fondamentalmente facendolo ricreare l'array, ad es INNER_KEY=($<env_key>). : .

Per esame:

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

Il problema era che non potevo fare direttamente qualcosa del tipo (non usando bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.