shell脚本参数验证是健壮性底线,需校验数量(用$#)、内容(如文件路径、正整数、取值范围)、类型(case处理标志),变量必须加引号,启用set -u/-e,错误提示须含具体值、约束和示例,参数错误统一exit 2。

Shell脚本中参数验证不是可选项,而是健壮性的底线。没做校验的脚本在生产环境极易因非法输入崩溃或误操作,尤其涉及文件路径、数字范围、开关标志时。
检查参数数量是否足够
多数脚本依赖固定位置的参数(如$1、$2),少传会导致逻辑错乱。用$#判断并提前退出更安全:
- 明确要求至少两个参数:
if [ $# -lt 2 ]; then echo "Usage: $0 <file><mode>"; exit 1; fi</mode></file> - 允许可选参数但强制前两个存在,比如
if [ $# -lt 2 ] || [ $# -gt 4 ]; then ... - 避免只依赖
[ -z "$1" ]——空字符串和未传参都为真,无法区分
验证参数内容是否合规
类型和格式错误比数量错误更隐蔽。针对不同场景选择合适校验方式:
- 检查是否为有效文件路径:
[ -f "$1" ] || { echo "Error: '$1' is not a regular file"; exit 1; } - 确认是正整数:
[[ "$1" =~ ^[0-9]+$ ]] || { echo "Error: '$1' must be a positive integer"; exit 1; } - 限定取值范围(如端口号):
if (( $1 65535 )); then echo "Port must be 1–65535"; exit 1; fi - 区分标志参数和普通参数:
case "$1" in -h|--help) show_help; exit 0;; -v) verbose=1; shift;; *) echo "Unknown option: $1"; exit 1;; esac
处理空格与特殊字符的安全边界
用户输入含空格、星号、换行符时,未加引号的变量展开会破坏逻辑甚至引发命令注入:
- 所有变量引用必须加双引号:
cp "$src" "$dst",而非cp $src $dst - 用
printf %q转义不可信输入(如日志记录):printf 'Running with arg: %q\n' "$1" - 避免
eval拼接用户输入;若必须动态执行,优先用函数或数组代替 - 设置
set -u(报错未定义变量)和set -e(任一命令失败即退出),增强默认防护
提供清晰友好的错误提示
报错信息要指出问题在哪、为什么错、怎么改,而不是只说“invalid argument”:
- 包含具体参数值:
echo "Error: '-m' requires a non-empty mode string, got '$mode'" - 说明约束条件:
echo "Log level must be one of: debug, info, warn, error" - 附带调用示例:
echo "Example: $0 /var/log/app.log info" - 统一退出码:参数错误用
exit 2(POSIX约定),便于上层脚本识别











