在bash
shell 中,我们可以定义一个f
函数
f(){ echo Hello; }
然后重新声明/覆盖它,没有任何错误或警告消息,
f(){ echo Bye; }
我相信有一种方法可以保护函数不被这种方式覆盖。
答案1
您可以使用or (相当于)将函数声明foo
为只读函数。这些内置实用程序的选项使它们充当函数的名称,而不是变量。readonly -f foo
declare -g -r -f foo
readonly
declare -g -r
-f
foo
foo
$ foo () { echo Hello; }
$ readonly -f foo
$ foo () { echo Bye; }
bash: foo: readonly function
$ unset -f foo
bash: unset: foo: cannot unset: readonly function
$ foo
Hello
正如您所看到的,使函数只读不仅可以防止它被覆盖,还可以防止它被取消设置(完全删除)。
目前(截至),如果使用shell 选项 ( ),bash-5.0.11
则尝试修改只读函数不会终止 shell 。 Chet,维护者,errexit
set -e
bash
说这是一个疏忽并且它将在下一个版本中进行更改。
更新:此问题已于 2019 年 10 月修复,因此,如果在shell 选项处于活动状态时尝试修改只读函数,则bash-5.1-alpha
任何5.1 或更高版本都将正确退出。bash
errexit
答案2
对@Kusalananda 的回答没什么评论。根据 bash 维护者的说法,在使用 .bashrc 时,更改只读函数将触发 shell 的终止set -e
。
我正在使用 Ubuntu 20.10 和更新的 bash 版本。不幸的是它似乎被打破了。
$ bash --version
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
测试文件
#!/usr/bin/env bash
set -e
test() {
echo "I'm test() function"
}
readonly -f test
test
test() { # should exit here
echo "I'm test() function (duplicated)"
}
test
输出
$ chmod +x test.sh; ./test.sh
I'm test() function
./test.sh: line 14: test: readonly function
I'm test() function
我已经使用最新的 bash 版本在 docker 容器内测试了这个脚本,它按预期工作。
GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-musl)