J'ai un script qui fait un certain nombre de choses différentes, dont la plupart ne nécessitent aucun privilège spécial. Cependant, une section spécifique, que j'ai contenue dans une fonction, a besoin des privilèges root.
Je ne souhaite pas exiger que le script entier s'exécute en tant que root, et je veux pouvoir appeler cette fonction, avec les privilèges root, à partir du script. Demander un mot de passe si nécessaire n'est pas un problème car il est surtout interactif de toute façon. Cependant, lorsque j'essaie d'utiliser sudo functionx
, j'obtiens:
sudo: functionx: command not found
Comme je m'y attendais, cela export
n'a pas fait de différence. J'aimerais pouvoir exécuter la fonction directement dans le script plutôt que de la décomposer et de l'exécuter en tant que script distinct pour un certain nombre de raisons.
Existe-t-il un moyen de rendre ma fonction "visible" pour sudo sans l'extraire, trouver le répertoire approprié, puis l'exécuter en tant que script autonome?
La fonction concerne une page elle-même et contient plusieurs chaînes, certaines entre guillemets doubles et d'autres entre guillemets simples. Il dépend également d'une fonction de menu définie ailleurs dans le script principal.
Je m'attendrais seulement à ce que quelqu'un avec sudo ANY puisse exécuter la fonction, car l'une des choses qu'il fait est de changer les mots de passe.
declare
elles aussi.Réponses:
J'admets qu'il n'y a pas de moyen simple et intuitif de le faire, et c'est un peu hackey. Mais vous pouvez le faire comme ceci:
Ou plus simplement:
Ça marche pour moi:
Fondamentalement,
declare -f
renvoie le contenu de la fonction, que vous passez ensuite enbash -c
ligne.Si vous souhaitez exporter toutes les fonctions de l'instance externe de bash, passez
FUNC=$(declare -f hello)
àFUNC=$(declare -f)
.Éditer
Pour répondre aux commentaires sur les devis, consultez cet exemple:
la source
echo "Hello!"
est en fait identique àecho Hello!
(c'est-à-dire que les guillemets doubles ne font aucune différence pour cette commande d'écho particulière). Dans de nombreuses circonstances / la plupart des autres, les guillemets doubles dans la fonction sont susceptibles de casser labash -c
commande.bash -xc
plutôt quebash -c
) et il ressemblebash
est assez intelligent pour les choses re-citation dans cette situation, même dans la mesure de remplacer les guillemets doubles avec des guillemets simples et changer'
de'\''
si nécessaire. Je suis sûr qu'il y aura des cas qu'il ne pourra pas gérer, mais cela fonctionne certainement pour au moins les cas simples et moyennement complexes - par exemple, essayezfunction hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello"
declare -f
imprime la définition de la fonction d'une manière qui peut être analysée à nouveau par bash, doncbash -c "$(declare -f)"
cela fonctionne correctement (en supposant que le shell externe est également bash). L'exemple que vous avez posté montre qu'il fonctionne correctement - où les guillemets ont été modifiés se trouve dans la trace , car bash imprime des traces dans la syntaxe du shell, par exemple essayezbash -xc 'echo "hello world"'
sudo yourFunction
n'est pas trouvé (sinon vous obtenez une erreur de segmentation de la récursivité)Le «problème» est qu'il
sudo
efface l'environnement (à l'exception d'une poignée de variables autorisées) et définit certaines variables sur des valeurs de sécurité prédéfinies afin de se protéger contre les risques de sécurité. en d'autres termes, ce n'est pas réellement un problème. C'est une fonctionnalité.Par exemple, si vous définissez
PATH="/path/to/myevildirectory:$PATH"
etsudo
que vous ne définissez pas PATH sur une valeur prédéfinie, tout script qui ne spécifie pas le nom de chemin complet pour TOUTES les commandes qu'il exécute (c'est-à-dire la plupart des scripts) doit chercher/path/to/myevildirectory
avant tout autre répertoire. Mettez des commandes commels
ougrep
ou d'autres outils communs et vous pouvez facilement faire ce que vous voulez sur le système.La façon la plus simple / la meilleure consiste à réécrire la fonction en tant que script et à l'enregistrer quelque part dans le chemin (ou spécifiez le chemin complet du script sur la
sudo
ligne de commande - ce que vous devrez faire de toute façon, sauf s'ilsudo
est configuré pour vous permettre pour exécuter N'IMPORTE QUELLE commande en tant que root), et le rendre exécutable avecchmod +x /path/to/scriptname.sh
Réécriture une fonction shell en tant que script est aussi simple que l' enregistrement que les commandes à l' intérieur de la définition de la fonction dans un fichier (sans
function ...
,{
et}
lignes).la source
sudo -E
Évite également de nettoyer l'environnement.J'ai écrit ma propre
Sudo
fonction bash pour cela, cela fonctionne pour appeler des fonctions et des alias:la source
Vous pouvez combiner des fonctions et des alias
Exemple:
sudo hello
fonctionne alorsla source
Voici une variante de la réponse de Will . Il implique un
cat
processus supplémentaire , mais offre le confort de heredoc. En résumé, cela se passe comme suit:Si vous voulez plus de matière à réflexion, essayez ceci:
La sortie est:
Ici, nous avons la
menu
fonction correspondant à celle de la question, qui est "définie ailleurs dans le script principal". Si «ailleurs» signifie que sa définition a déjà été lue à ce stade lors de l'sudo
exécution de la fonction exigeante , alors la situation est analogue. Mais il n'a peut-être pas encore été lu. Il se peut qu'une autre fonction déclenche sa définition. Dans ce cas,declare -f menu
doit être remplacé par quelque chose de plus sophistiqué, ou le script entier corrigé d'une manière que lamenu
fonction est déjà déclarée.la source
menu
fonction aurait été déclarée avant ce point, comme on l'f
appelle depuis un menu.En supposant que votre script soit (a) autonome ou (b) peut source ses composants en fonction de son emplacement (plutôt que de se rappeler où se trouve votre répertoire personnel), vous pouvez faire quelque chose comme ceci:
$0
chemin d'accès du script, en utilisant celui de lasudo
commande, et passez une option que le script vérifiera, pour appeler la mise à jour du mot de passe. Tant que vous comptez sur la recherche du script dans le chemin (plutôt que de simplement l'exécuter./myscript
), vous devriez obtenir un chemin d'accès absolu$0
.sudo
exécute le script, il a accès aux fonctions dont il a besoin dans le script.uid
et se rendrait compte qu'il était exécuté en tant qu'utilisateur root , et voyant qu'il a l'option définie pour lui dire de mettre à jour le mot de passe, allez faire cette.Les scripts peuvent se reproduire pour diverses raisons: la modification des privilèges en fait partie.
la source