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
.