在shell脚本中使用只读变量的用法

16

在编写shell脚本时,尽可能使用只读变量是否是良好的编程实践?或者它是否有任何缺点?例如,如果我想编写一些由多个脚本文件组成且使用不可变文件路径的脚本,那么声明这些路径是否有意义:

readonly LOGS
export LOGS 
LOGS="/some/path"

另一个问题:将庞大而难读的Shell脚本代码拆分成单独的文件是个好主意吗?非常感谢您的回答。


2
到目前为止,我还没有看到任何Bashism是良好的编程实践。如果你想学习干净的Shell脚本编程,请使用纯sh。不能轻松完成的事情也不应该用Bash来完成。 - Jo So
只读变量在安全方面非常有用。要了解原因,请在命令行上设置一个只读变量,然后看看尝试更改它有多困难-据我所知,您必须使用调试器(例如gbd attach <pid>)来破解Bash才能更改只读变量的值。 - user4401178
@A.Danischewski - 或者启动一个新的 shell 进程。 - Mark Reed
4个回答

18

听起来你可能认为readonly比它实际上做的更多。首先,只读状态不会被导出到环境中或被子进程继承:

$ declare -rx LOGS=hello
$ LOGS=goodbye
bash: LOGS: readonly variable
$ bash -c 'echo "$LOGS"'
hello
$ bash -c 'LOGS=goodbye; echo "$LOGS"'
goodbye
$ 

1
很好的观点,但是可以轻松地通过使用“.”而不是调用脚本作为子进程来解决这个问题。 - figtrap

7

只读变量的一个经典用途是与TMOUT一起使用。将此变量设置为非零值将在TMOUT秒的不活动时间(即没有键盘输入)后注销交互式终端会话。为了防止聪明用户覆盖设置,请使用readonly

readonly TMOUT=60

完成这个操作之后,就没有了其他的方式。
export TMOUT=0

3
可以轻松地使用 exec bash 解决此问题。 如果需要保持 TMOUT 不再设置,可以使用 --norc 参数。 - Mark Reed

6
通常来说,在使用任何编程语言时,使用只读变量和模块化程序都是好的选择。
只读变量能够防止常见的错误源,并且有助于提高代码可读性和可维护性。了解一个变量的值是可以信赖的,使您能够更好地推理程序,并在后续中对该变量做出假设 - 如果该变量是可变的,则无法做到这一点。
模块化提高了代码的可维护性和可重复使用性。更多的模块意味着更细粒度的单元,可以在不同的情况下进行重用,代码更简洁易读,如果您的模块是独立的,则部件之间的交互较少,修改也就不会影响其它部分。

2
我认为在bash中使用只读变量并不实用。我想不出有什么问题可以通过将变量设置为只读而避免。这种限制违反了bash动态特性的本质。还有其他更常见的问题(如拼写错误或忘记将变量声明为局部变量),无论如何都无法避免。
如果您想要拆分代码,请尝试仅拆分“函数”,而不是代码块。如果您知道“source〜/myscript.sh”实际上没有做任何事情,那么重用小部件会更容易。

1
谢谢。但是只读变量没有任何缺点,对吧? - user1812379
5
实际上,只读变量具有其值。如果您维护着许多交叉引用的脚本,将变量标记为不可变是非常有意义的!正如@MarkReed所提到的,它们实际上并不是不可变的,但当其他人开始阅读您的“东西”时,他们会有这样一个想法:这个变量不应该改变!这真的很有用,可以使脚本更加易读。我真的认为在全局变量中共享状态是一种糟糕的做法,但众所周知,Bash没有考虑任何这些问题。 - egelev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接