Как защитить функцию bash от переопределения?

13

В bashоболочке мы можем определить функцию fс

f(){ echo Hello; }

а затем повторно объявить / переопределить его, без каких-либо сообщений об ошибках или предупреждений, с помощью

f(){ echo Bye; }

Я считаю, что есть способ защитить функции от переопределения таким образом.

KYB
источник
2
так же , как с переменными, с typeset -r: typeset -rf f.
Мосви
3
илиreadonly -f f
мосви

Ответы:

25

Вы можете объявить fфункцию только для чтения, используя readonly -f fили declare -g -r -f f( readonlyэквивалентно 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) попытка изменить функцию только для чтения не приведет к завершению оболочки, если она использует параметр errexitоболочки ( set -e). Чет, bashсопровождающий, говорит, что это недосмотр и что он будет изменен в следующем выпуске.

Кусалананда
источник
Попытка переопределить функцию создает сообщение bash: f: readonly functionи ненулевой код состояния, но не завершается, если errexitопция включена.
KYB
@kyb Я тоже это заметил. Я не уверен, что это ошибка bash, но я попрошу один из bashсписков рассылки, чтобы быть уверенным.
Кусалананда
хорошо, пожалуйста, обновите свой ответ, когда вы будете уверены в этом поведении.
KYB
1
@kyb Стефан Шазелас и Грег Вудледж взвесили этот вопрос, оба с правдоподобными объяснениями. Стефан предполагает, что bashвыход происходит только тогда, когда set -eдействует, когда POSIX требует этого (а readonly -fне POSIX). Грег отмечает, что в bashруководстве никогда не упоминается «сбой в объявлении функции» в качестве причины для errexitзапуска выхода (если только объявление функции не считается составной командой, что, как он уверен, не делает). Тема
Кусалананда
@kyb Я также заметил, что вы никогда не говорите ничего о errexitили set -eв своем вопросе.
Кусалананда