psql -v ON_ERROR_STOP=1失效,脚本报错无法终止执行求助
解决psql执行报错但脚本不终止的问题
核心原因
默认情况下,psql执行查询时遇到普通错误(如函数不存在、语法错误)只会输出错误信息,但退出码仍然为0。只有设置ON_ERROR_STOP=1,才会让psql在查询出错时立即终止并返回非0退出码。如果你的-v ON_ERROR_STOP=1无效,大概率是用法问题或脚本未正确检查退出码。
具体解决步骤
1. 正确设置ON_ERROR_STOP参数
确保ON_ERROR_STOP=1参数正确传递给psql,有两种标准写法:
# 写法1:使用-v参数 psql -v ON_ERROR_STOP=1 -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}($day_begin,$day_end)" # 写法2:使用--set参数(可读性更强) psql --set ON_ERROR_STOP=1 -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}($day_begin,$day_end)"
对于PostgreSQL 11及以上版本,还可以用简化参数--exit-on-error,效果完全等价于ON_ERROR_STOP=1:
psql --exit-on-error -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}($day_begin,$day_end)"
2. 强制脚本检测退出码并终止
即使psql返回了非0退出码,bash脚本默认不会自动终止,需要手动处理:
- 在
dbb_promo_list.sh开头添加set -e,让脚本在任何命令返回非0时立即终止:
#!/bin/bash set -e # 后续变量定义、psql命令等 psql -v ON_ERROR_STOP=1 -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}($day_begin,$day_end)"
- 或者手动检查psql的退出码,自定义终止逻辑:
psql -v ON_ERROR_STOP=1 -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}($day_begin,$day_end)" exitcode=$? if [ $exitcode -ne 0 ]; then echo "psql执行失败,错误码:$exitcode" exit $exitcode fi
3. 修复SQL语句的变量引用问题
如果$day_begin或$day_end是字符串类型,未加引号会导致SQL语法错误,这种情况下即使设置了ON_ERROR_STOP=1,也会触发错误。建议给字符串变量添加单引号:
psql -v ON_ERROR_STOP=1 -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}('$day_begin','$day_end')"
如果变量可能包含特殊字符(如单引号),更安全的做法是使用psql的变量传递,避免SQL注入:
psql -v ON_ERROR_STOP=1 -v day_begin="$day_begin" -v day_end="$day_end" -U $DB_USERNAME -h $DB_HOST -p $DB_PORT -d $DATABASE -c "SELECT schema.${PROCEDURE}(:day_begin,:day_end)"
4. 确保错误输出未被屏蔽
检查脚本中是否将psql的错误输出(stderr)重定向到了/dev/null(比如psql ... 2>/dev/null),这种情况下你看不到错误信息,也可能导致退出码检测失效,需去掉这类重定向。
验证方法
执行脚本时,故意写错函数名模拟错误,然后执行echo $?检查退出码。如果返回非0值,说明psql的错误捕获生效,再结合set -e或手动判断逻辑即可实现脚本终止。
内容的提问来源于stack exchange,提问作者Kevin William
相关产品推荐
相关产品推荐

