17

In the bash shell, we can define a function f with

f(){ echo Hello; } 

and then redeclare/override it, without any error or warning messages, with

f(){ echo Bye; } 

I believe there is a way to protect functions from being overridden in this way.

2
  • 2
    the same as with variables, with typeset -r: typeset -rf f. Commented Sep 26, 2019 at 7:25
  • 3
    or readonly -f f Commented Sep 26, 2019 at 7:26

2 Answers 2

33

You may declare a function foo as a read-only function using readonly -f foo or declare -g -r -f foo (readonly is equivalent to declare -g -r). It's the -f option to these built-in utilities that makes them act on foo as the name of a function, rather than on the variable 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 

As you can see, making the function read-only not only protects it from getting overridden, but also protects it from being unset (removed completely).


Currently (as of bash-5.0.11), trying to modify a read-only function would not terminate the shell if one is using the errexit shell option (set -e). Chet, the bash maintainer, says that this is an oversight and that it will be changed with the next release.

Update: This was fixed during October 2019 for bash-5.1-alpha, so any bash release 5.1 or later would exit properly if an attempt to modify a read-only function is made while the errexit shell option is active.

6
  • Attempt to override function produces message bash: f: readonly function and non-zero status code, but does not exit if errexit option enabled. Commented Sep 27, 2019 at 9:55
  • @kyb I noticed this as well. I'm not certain it's a bug in bash, but I will ask on one of the bash mailing lists to be sure. Commented Sep 27, 2019 at 10:03
  • good, please update your answer when you will be sure about this behavior. Commented Sep 27, 2019 at 14:19
  • 1
    @kyb Both Stephane Chazelas and Greg Wooledge weighed in on that question, both with plausible explanations. Stephane suggests that bash only exits when set -e is in effect when POSIX requires it to (and readonly -f is not POSIX). Greg points out that the bash manual never mentions "failure in function declaration" as reason for errexit to trigger an exit (unless a function declaration counts as a compound command, which he's pretty sure it does not). The thread is ongoing here: lists.gnu.org/archive/html/help-bash/2019-09/msg00039.html Commented Sep 27, 2019 at 20:54
  • @kyb I'm also noticing that you never say anything about errexit or set -e in your question. Commented Sep 27, 2019 at 20:58
1

Little remark to @Kusalananda's answer. According to what bash maintainer said that changing a read-only function shall trigger the termination of the shell when using set -e.

I'm using Ubuntu 20.10 with a much newer bash version. Unfortunately it seems to be broken.

$ bash --version GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu) 

test.sh

#!/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 

Output

$ chmod +x test.sh; ./test.sh I'm test() function ./test.sh: line 14: test: readonly function I'm test() function 

I've tested this script inside a docker container using latest bash version and it works as expected.

GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-musl) 
1
  • Thank you for updating this thread Commented May 17, 2021 at 9:56

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.