Como proteger a função bash de ser substituída?

12

No bashshell, podemos definir uma função fcom

f(){ echo Hello; }

redeclarar / substituir, sem nenhum erro ou mensagem de aviso, com

f(){ echo Bye; }

Eu acredito que existe uma maneira de proteger as funções de serem substituídas dessa maneira.

kyb
fonte
2
o mesmo que com variáveis, com typeset -r: typeset -rf f.
mosvy
3
oureadonly -f f
mosvy 26/09/19

Respostas:

25

Você pode declarar fcomo uma função somente leitura usando readonly -f fou declare -g -r -f f( readonlyé equivalente a declare -g -r). É a -fopção para esses utilitários internos que os faz agir fcomo o nome de uma função, e não na variável 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

Como você pode ver, tornar a função somente leitura não apenas a impede de ser substituída, mas também a de ser desmarcada (removida completamente).


Atualmente (a partir de bash-5.0.11), tentar modificar uma função somente leitura não encerraria o shell se alguém estiver usando a errexitopção shell ( set -e). Chet, o bashmantenedor, diz que isso é um descuido e que será alterado no próximo lançamento.

Kusalananda
fonte
A tentativa de substituir a função produz mensagem bash: f: readonly functione código de status diferente de zero, mas não sai se a errexitopção estiver ativada.
kyb 27/09/19
@kyb Notei isso também. Não tenho certeza de que seja um bug bash, mas pedirei em uma das bashlistas de discussão para ter certeza.
Kusalananda
bom, atualize sua resposta quando tiver certeza sobre esse comportamento.
kyb 27/09/19
1
@kyb Tanto Stephane Chazelas quanto Greg Wooledge abordaram essa questão, ambos com explicações plausíveis. Stephane sugere que bashsó sai quando set -eestá em vigor quando o POSIX exige (e readonly -fnão é POSIX). Greg ressalta que o bashmanual nunca menciona "falha na declaração de função" como motivo para errexitacionar uma saída (a menos que uma declaração de função conte como um comando composto, o que ele tem certeza de que não). O tópico está em andamento aqui: lists.gnu.org/archive/html/help-bash/2019-09/msg00039.html
Kusalananda
@kyb Também estou percebendo que você nunca diz nada sobre errexitou está set -eem sua pergunta.
Kusalananda