readonly 是 Bash 内建的运行时变量保护机制,用于锁定核心配置变量(如常量、路径、连接参数等),防止赋值或 unset;需显式命名、值确定后立即设置,仅作用于当前 shell 且不可撤销。

在 Linux Shell 脚本中,用 readonly 命令锁定变量是最直接、内建且无需额外依赖的防篡改手段。它不是“语法修饰”,而是 Bash 的硬性运行时保护——一旦设为只读,任何后续赋值或 unset 操作都会被 shell 明确拒绝,报错如 bash: VAR: readonly variable,从源头阻断意外覆盖或恶意修改。
哪些变量必须设为只读
重点保护那些参与核心逻辑、值固定、不该被运行时干扰的配置项:
-
硬编码常量:如
APP_VERSION="4.1.0"、MAX_RETRY=3、CONFIG_DIR="/etc/myapp" -
路径类变量:尤其是经
realpath解析后的绝对路径,例如LOG_PATH="$(realpath /var/log/app)",避免因cd或拼接错误导致命令失效 -
服务连接参数:如
DB_HOST="10.0.2.10"、API_TIMEOUT=15,防止条件分支或子脚本擅自更改行为 -
已导出的关键环境变量:先
export PATH,再readonly PATH,可阻止脚本执行PATH="/tmp:$PATH"引入危险路径
正确设置只读变量的两种写法
必须在变量已有确定值之后立即锁定,否则等于未生效:
-
一步到位(推荐):语义清晰、不易遗漏,适合新定义变量
readonly DB_PORT=5432 LOG_LEVEL="error" BIN_DIR="/opt/app/bin" -
两步操作:适用于已存在变量(如从配置文件 source 进来)
source ./config.env<br>readonly DB_HOST CONFIG_FILE APP_ENV
注意:不能写 readonly $VARNAME 或 readonly ${VAR} —— 必须显式写出变量名本身。
验证是否真正锁住
别只看脚本里写了 readonly,要实测拦截效果:
- 列出所有只读项:
readonly -p(输出带declare -r前缀,适合脚本解析) - 检查单个变量:
declare -p VARNAME 2>/dev/null | grep '^declare -r',返回 0 表示已生效 - 主动测试修改:
VARNAME="new"应立刻报错,这不是故障,是防护起效 - 尝试清除:
unset VARNAME会提示cannot unset: readonly variable
关键限制与避坑提醒
readonly 是强约束,但有明确边界:
- 仅对当前 shell 及其派生的子 shell 有效,不影响父进程、其他终端会话或系统级环境
- 不可撤销:没有
readonly -u或declare +r;若需修改,只能重启 shell 或重构逻辑(如用外部配置文件按需读取) - 数组和函数需显式指定:
readonly -a arr_name、readonly -f func_name - 对目录或文件内容无影响——它保护的是变量本身,不是变量指向的路径下的文件


















