Réponses:
sudo su -
, qui est une manière compliquée d'écrire sudo -i
, construit un environnement vierge. C'est le point d'un shell de connexion. Même un simple sudo
supprime la plupart des variables de l'environnement. De plus, sudo
c'est une commande externe; il n'y a aucun moyen d'élever les privilèges dans le script shell lui-même, uniquement pour exécuter un programme externe ( sudo
) avec des privilèges supplémentaires, et cela signifie que les variables shell (c'est-à-dire les variables non exportées) et les fonctions définies dans le shell parent ne seront pas disponibles dans la coquille d'enfant.
Vous pouvez transmettre des variables d'environnement en n'appelant pas un shell de connexion ( sudo bash
au lieu de sudo su -
ou sudo -i
) et en configurant sudo pour laisser passer ces variables (avec Defaults !env_reset
ou Defaults env_keep=…
dans le sudoers
fichier). Cela ne vous aidera pas pour les fonctions (bien que bash dispose d'une fonction d'exportation de fonctions, sudo la bloque).
La manière normale d'obtenir vos fonctions dans le shell enfant serait de les définir là-bas. Prenez soin de citer: si vous utilisez <<EOF
pour le document ici, le contenu du document ici est d'abord développé par le shell parent, et le résultat de cette expansion devient le script que le shell enfant voit. Autrement dit, si vous écrivez
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
cela affiche le nom de l'utilisateur d'origine, pas l'utilisateur cible. Pour éviter cette première phase d'expansion, citez le marqueur de document ici après l' <<
opérateur:
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
Donc, si vous n'avez pas besoin de transmettre des données du shell parent au shell enfant, vous pouvez utiliser un document cité ici:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
Bien que vous puissiez utiliser un marqueur de document non cité ici pour transmettre des données du shell parent au shell enfant, cela ne fonctionne que si les données ne contiennent aucun caractère spécial. C'est parce que dans un script comme
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
la sortie de whoami
devient un peu de code shell, pas une chaîne. Par exemple, si la whoami
commande est retournée, "; rm -rf /; "true
le shell enfant exécutera la commande echo ""; rm -rf /; "true"
.
Si vous devez transmettre des données à partir du shell parent, un moyen simple consiste à les passer en arguments. Appelez explicitement le shell enfant et passez-lui les paramètres positionnels:
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Si vous avez plusieurs variables à passer, il sera plus lisible de les passer par leur nom. Appelez env
explicitement pour définir les variables d'environnement pour le shell enfant.
#!/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
Notez que si vous vous attendiez à ce /etc/profile
que l'utilisateur cible ~/.profile
soit lu, vous devrez les lire explicitement ou appeler à la bash --login
place de sh
.
Cela ne fonctionne pas car la fonction log_f
n'est pas déclarée dans le sudo su -
shell que vous lancez. Au lieu:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
Vous devez obtenir la fonction définie dans le sous-shell racine. Cela pourrait le faire, mais ... Je ne sais pas ce que la plupart de ces choses font. Au moins - tant que ni sudo
ni n'a su
besoin de stdin pour lire un mot de passe - cela devrait être log_f()
déclaré.
J'espère que vous entendez étendre ces valeurs dans l'entrée du shell racine, soit dit en passant. Si vous ne voulez pas le faire, vous devez citer EOF
et les vars eux-mêmes.
Dans mon cas , je devais passer un tableau et avait quelques problèmes, mais avec un succès après un certain temps en faisant écho aux valeurs du tableau à un env
-key et enveloppant le code destiné à bash -c '<intended code>'
, et ont essentiellement il recréer le tableau, par exemple .: INNER_KEY=($<env_key>)
.
Par exemple:
#!/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
Le problème était que je ne pouvais pas faire directement quelque chose comme ceci (sans utiliser bash -c '...'
):
FOO=($PLUGINS);
for pl in ${FOO[@]};
...