Comment protéger la fonction bash contre toute substitution?

13

Dans le bashshell, nous pouvons définir une fonction favec

f(){ echo Hello; }

puis redéclarer / remplacer, sans aucun message d'erreur ou d'avertissement, avec

f(){ echo Bye; }

Je pense qu'il existe un moyen de protéger les fonctions contre toute substitution de cette manière.

kyb
la source
2
la même que celle des variables, avec typeset -r: typeset -rf f.
mosvy
3
oureadonly -f f
mosvy

Réponses:

25

Vous pouvez déclarer en ftant que fonction en lecture seule en utilisant readonly -f fou declare -g -r -f f( readonlyéquivaut à declare -g -r). C'est l' -foption de ces utilitaires intégrés qui les fait agir fcomme le nom d'une fonction, plutôt que comme la variable f.

$ f(){ echo Hello; }
$ readonly -f f
$ f(){ echo Bye; }
bash: f: readonly function
$ unset -f f
bash: unset: f: cannot unset: readonly function
$ f
Hello

Comme vous pouvez le voir, le fait de rendre la fonction en lecture seule la protège non seulement de la substitution, mais la protège également de la désactivation (supprimée complètement).


Actuellement (à partir de bash-5.0.11), essayer de modifier une fonction en lecture seule ne terminerait pas le shell si l'on utilise l' errexitoption shell ( set -e). Chet, le bashmainteneur, dit qu'il s'agit d'une erreur et qu'elle sera modifiée avec la prochaine version.

Kusalananda
la source
La tentative de remplacement de la fonction produit un message bash: f: readonly functionet un code d'état différent de zéro, mais ne se ferme pas si l' errexitoption est activée.
kyb
@kyb J'ai également remarqué cela. Je ne suis pas certain que ce soit un bug bash, mais je vais demander sur l'une des bashlistes de diffusion pour être sûr.
Kusalananda
bien, veuillez mettre à jour votre réponse lorsque vous serez sûr de ce comportement.
kyb
1
@kyb Stéphane Chazelas et Greg Wooledge ont pesé sur cette question, tous deux avec des explications plausibles. Stéphane suggère que bashne quitte que lorsque set -eest en vigueur lorsque POSIX l' exige (et readonly -fn'est pas POSIX). Greg fait remarquer que le bashmanuel ne mentionne jamais «l'échec de la déclaration de fonction» comme raison errexitde déclencher une sortie (à moins qu'une déclaration de fonction ne compte comme une commande composée, ce qu'il est sûr qu'il ne fait pas). Le fil est en cours ici: lists.gnu.org/archive/html/help-bash/2019-09/msg00039.html
Kusalananda
@kyb Je remarque également que vous ne dites jamais rien errexitni set -edans votre question.
Kusalananda