如何保护bash功能不被覆盖?


13

bash外壳中,我们可以f使用

f(){ echo Hello; }

然后使用以下命令重新声明/覆盖它,没有任何错误或警告消息

f(){ echo Bye; }

我相信,有一种方法可以防止功能被这种方式覆盖。


2
与变量相同,带有typeset -rtypeset -rf f
mosvy

3
readonly -f f
mosvy

Answers:


25

您可以f使用readonly -f fdeclare -g -r -f freadonly等同于declare -g -r)声明为只读函数。-f这些内置实用程序的选项使它们充当f函数的名称,而不是变量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

如您所见,将函数设置为只读不仅可以防止其被覆盖,还可以防止其被设置(完全删除)。


目前(截至bash-5.0.11),试图如果是使用修改只读功能不会终止Shell errexit外壳选项(set -e)。bash维护者Chet 说,这是一个疏忽,它将在下一版本中进行更改。


尝试覆盖功能会生成消息bash: f: readonly function和非零状态代码,但是如果errexit启用了选项,则不会退出。
kyb

@kyb我也注意到了这一点。我不确定这是中的错误bash,但我会要求其中一个bash邮件列表进行确认。
库萨兰达

很好,请在确定此行为后更新您的答案。
kyb

1
@kyb Stephane Chazelas和Greg Wooledge在这个问题上都提出了一个合理的解释。Stephane建议bashset -e在POSIX 要求(而readonly -f不是POSIX)生效时退出。Greg指出,该bash手册从未提及“函数声明失败”作为errexit触发退出的原因(除非函数声明算作复合命令,他很确定不会)。该线程正在此处进行:lists.gnu.org/archive/html/help-bash/2019-09/msg00039.html
库萨兰达

@kyb我也注意到,您从来不说任何事情errexit或者set -e在你的问题。
库萨兰达
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.