Bash for循环批量执行SQL文件仅运行首个文件问题排查
问题根因
循环仅执行第一个SQL文件的问题由两个原因共同导致:
- Bash数组遍历语法错误:写法
for file in ${arrIN}仅会读取数组的第一个元素(等价于${arrIN[0]}),本身就不会遍历数组的全部成员。 sqlplus默认会抢占Shell的标准输入流:哪怕数组遍历语法写对,sqlplus启动后会持续读取当前脚本的标准输入等待交互指令,直接吞掉循环后续需要读取的文件列表内容,导致循环提前终止。
修正后可直接运行的代码
#!/bin/bash # 先打印数组长度做校验,确认所有SQL文件都已被正确读入数组 echo "待执行SQL文件总数: ${#arrIN[@]}" # 遍历数组必须使用 "${arrIN[@]}" 写法,双引号用于兼容带空格/特殊字符的文件路径 for file in "${arrIN[@]}"; do echo "Executing ${file}.." # 给sqlplus重定向空输入,避免它抢占标准输入导致循环中断;变量全部加双引号避免特殊字符解析错误 sqlplus "${db_user}/${db_password}@${db_host}:1521/${db_sid}" @"${file}" < /dev/null # 可选:执行失败立即终止,避免后续SQL在错误状态下运行 if [ $? -ne 0 ]; then echo "执行${file}出错,批量任务终止" exit 1 fi done
关键注意事项
- 禁止使用
${arrIN}、不带引号的${arrIN[*]}写法遍历数组:前者仅取第一个元素,后者不带引号时会把所有元素拆成零散的字符串,遇到带空格的文件名会直接解析错误。 - 所有涉及路径、连接串的变量必须用双引号包裹:避免密码、文件路径中包含
@、空格、/等特殊字符时,命令被错误拆分解析。 - 给sqlplus加
< /dev/null是循环场景下的必须配置:不止是sqlplus,ssh、ftp、mysql等带交互模式的命令在Shell循环中运行时,都需要做类似的输入重定向,否则都会出现抢占标准输入导致循环提前结束的问题。
内容的提问来源于stack exchange,提问作者Stella Hansen
相关产品推荐
相关产品推荐

