Shell读写配置文件的关键在于稳定性、性能与可维护性:读取推荐mapfile或IFS='='的while循环,写入需备份、精准替换或条件追加,处理注释/引号/段落需组合grep/awk,且必须校验文件权限、写入结果及并发锁。

Shell里读写配置文件,关键不在“能不能”,而在“稳不稳、快不快、好不好维护”。运维场景下,配置文件常被脚本反复读取甚至动态修改,用错方法容易丢数据、漏字段、卡性能,尤其在日志分析、服务启停、批量部署时特别明显。
读取配置文件:别只靠while read
逐行读取看似直观,但while read在循环中会创建子shell,导致变量作用域丢失;大文件还拖慢速度。更稳妥的做法是:
- 小配置(几百行以内):直接用mapfile -t array < config.conf,整份载入数组,${#array[@]}得行数,${array[0]}取首行,干净利落
- 带等号的键值对(如port=8080):用while IFS='=' read -r key value,自动按=切分,避免手动cut或awk出错
- 必须逐行处理时:加-r防止反斜杠误转义,用IFS=保留行首尾空格,避免配置缩进被吃掉
写入配置文件:覆盖要谨慎,追加有讲究
运维中改配置不是“重写就完事”,一不留神就清空关键项。安全写法有三类:
- 覆盖写入:先cp config.conf config.conf.bak备份,再用echo "timeout=30" > config.conf——仅适合全新生成配置
- 精准替换:用sed -i 's/^timeout=.*/timeout=60/' config.conf,^确保只改开头的timeout行,.*吞掉旧值,不碰其他字段
- 条件追加:检查是否存在再写,比如grep -q '^log_level=' config.conf || echo "log_level=info" >> config.conf,避免重复写入
处理特殊字符和结构化配置
真实配置常含井号注释、引号包裹值、空行分隔段落。硬解析易翻车,推荐组合策略:
- 跳过注释与空行:grep -v '^[[:space:]]*#' config.conf | grep -v '^[[:space:]]*$'
- 提取带引号的值:awk -F'=' '/^path=/ {gsub(/^\"|\"$/, "", $2); print $2}' config.conf,自动剥掉双引号
- 按段落处理(如[database]区块):awk '/^\[database\]$/,/^\[/ {if(!/^\[/&!/^$/)print}' config.conf,精准截取区间
错误处理不能省
运维脚本跑在服务器上,没人盯着报错。每次读写前必须校验:
- 检查文件是否存在且可读:[[ -f config.conf && -r config.conf ]] || { echo "配置文件缺失或无读取权限"; exit 1; }
- 写入后验证内容:grep -q 'expected_key=' config.conf || { echo "写入失败,key未生效"; exit 1; }
- 避免并发冲突:若多进程可能同时改同一配置,加flock锁,例如flock /tmp/config.lock -c 'sed -i ... config.conf'


















