shell脚本安全读取变量需明确来源、控制范围、防范注入:命令行参数用"$1"等加引号并校验个数;read交互输入加-s/-r选项;环境变量须校验并unset高危项;配置文件禁用source,推荐awk/grep解析。

在 Shell 脚本中安全读取变量,核心是明确来源、控制范围、防范注入,并适配使用场景。不加区分地读取或拼接变量,容易导致路径截断、命令执行、权限越界等问题。
从命令行参数安全读取
位置参数($1、$2等)是最常见的外部输入源,但必须做边界保护:
- 始终用双引号包裹:如 "$1"、"$2",防止含空格、通配符或换行的参数被错误拆分或展开
- 用 $# 检查参数个数,避免未提供时引用空值:例如 [ $# -lt 2 ] && { echo "缺参数"; exit 1; }
- 需逐个处理未知数量参数时,用 "$@" 遍历,而非 $*:前者保持每个参数独立,后者会粘合成单个字符串
- 必要时用 shift 移动参数,配合循环处理选项与参数混合的情况
从用户交互安全读取
使用 read 命令接收键盘输入,重点在于防意外解析和隐藏敏感内容:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 密码类输入务必加 -s 选项:如 read -s -p "密码: " PASS,避免明文回显
- 提示信息用 -p 显式给出,避免用户混淆输入上下文
- 含反斜杠的输入需加 -r:否则 \n 等会被转义,影响原始内容
- 限制输入长度或超时可增强健壮性:如 read -t 30 -n 64 INPUT(30秒内最多读64字符)
从环境变量安全读取
环境变量(如 PATH、HOME)由父进程继承,可能被污染,不可盲目信任:
- 只读取明确需要的变量,避免直接用 env 全量导入
- 对关键变量做合法性校验:例如检查 $PATH 是否包含非标准路径(~/bin、.),发现则重置为安全默认值
- 高危变量如 LD_PRELOAD、PYTHONPATH 应在脚本开头 unset
- 敏感值(如 API 密钥)不应设为环境变量;若必须,确保仅在最小作用域内导出且不被子进程继承
从文件安全读取变量
从配置文件加载变量时,避免执行任意内容,优先用结构化方式解析:
- 禁用 source 或 . 加载不受信文件:它们会执行其中所有 shell 代码,风险极高
- 推荐用 awk -F= '/^KEY=/ {print $2}' file 提取键值,或用 grep '^KEY=' file | cut -d= -f2-
- 若文件格式可控,可使用 set -a; source config.sh; set +a(仅导入,不执行函数),但仍需确保文件权限为 600 或 644 且属主可信
- 读取后建议做非空和格式校验,例如 [ -z "$DB_HOST" ] && { echo "DB_HOST 未设置"; exit 1; }
不复杂但容易忽略。关键不是“能不能读”,而是“从哪来、有没有验、传给谁用”。










