Bagaimana cara melindungi fungsi bash dari penggantian?

12

Dalam bashshell, kita dapat mendefinisikan suatu fungsi fdengan

f(){ echo Hello; }

dan kemudian mendeklarasikan ulang / menimpanya, tanpa ada pesan kesalahan atau peringatan, dengan

f(){ echo Bye; }

Saya percaya ada cara untuk melindungi fungsi agar tidak ditimpa dengan cara ini.

Kyb
sumber
2
sama dengan variabel, dengan typeset -r: typeset -rf f.
Mosvy
3
ataureadonly -f f
mosvy

Jawaban:

25

Anda dapat mendeklarasikan fsebagai fungsi hanya baca menggunakan readonly -f fatau declare -g -r -f f( readonlysetara dengan declare -g -r). Ini adalah -fopsi untuk utilitas bawaan ini yang membuat mereka bertindak fsebagai nama fungsi, bukan pada variabel 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

Seperti yang Anda lihat, membuat fungsi read-only tidak hanya melindunginya dari penggantian, tetapi juga melindunginya dari tidak disetel (dihapus sepenuhnya).


Saat ini (per bash-5.0.11), mencoba untuk memodifikasi fungsi read-only tidak akan menghentikan shell jika seseorang menggunakan errexitopsi shell ( set -e). Chet, sang bashpengelola, mengatakan bahwa ini adalah kekhilafan dan bahwa itu akan diubah dengan rilis berikutnya.

Kusalananda
sumber
Mencoba untuk mengesampingkan fungsi menghasilkan pesan bash: f: readonly functiondan kode status tidak nol, tetapi tidak keluar jika errexitopsi diaktifkan.
kyb
@ Kyb Saya perhatikan ini juga. Saya tidak yakin ini bug bash, tetapi saya akan bertanya pada salah satu bashmilis untuk memastikan.
Kusalananda
bagus, harap perbarui jawaban Anda saat Anda yakin tentang perilaku ini.
kyb
1
@ Kyb Baik Stephane Chazelas dan Greg Wooledge mempertimbangkan pertanyaan itu, keduanya dengan penjelasan yang masuk akal. Stephane menyarankan bahwa bashhanya keluar saat set -eberlaku ketika POSIX mengharuskannya (dan readonly -fbukan POSIX). Greg menunjukkan bahwa bashmanual tidak pernah menyebutkan "kegagalan dalam deklarasi fungsi" sebagai alasan untuk errexitmemicu keluar (kecuali jika deklarasi fungsi dianggap sebagai perintah majemuk, yang dia cukup yakin tidak). Utas sedang berlangsung di sini: lists.gnu.org/archive/html/help-bash/2019-09/msg00039.html
Kusalananda
@ Kyb Saya juga memperhatikan bahwa Anda tidak pernah mengatakan apa-apa tentang errexitatau set -edalam pertanyaan Anda.
Kusalananda