Linux下sqlcmd执行存储过程如何捕获完整执行日志到输出文件
问题描述
- 在Linux主机上执行如下sqlcmd命令运行存储过程:
sqlcmd -S<server> -d<db> -U<login> -P<pwd> -i /scripts/StoredProcedure1.sql -o /logs/output.log - 在SSMS中手动执行该存储过程时,可正常返回如下执行成功提示:
Commands completed successfully. Completion time: 2022-06-12T18:28:18.4580782-04:00 - 执行上述命令后生成的
output.log文件大小为0字节,无法捕获到上述执行成功提示。 - 已尝试如下方案均未生效:
- 添加
-r[0 | 1]参数尝试将消息输出到stderr - 调整
-m error_level参数修改错误捕获级别 - 参考Shell重定向规则调整输出重定向配置
- 添加
- 核心诉求:确认参数使用/组合方式是否存在问题,找到可捕获完整执行日志的可行方案。
解决方案
Linux版mssql-tools里的sqlcmd和Windows版实现逻辑差很多,你碰到的空日志问题基本是踩了参数和重定向的坑,按下面的方法调就能解决:
- 放弃单独使用
-o参数写日志,改用参数组合+shell原生重定向,正确命令如下:
参数说明:sqlcmd -S<server> -d<db> -U<login> -P<pwd> -b -r1 -i /scripts/StoredProcedure1.sql > /logs/output.log 2>&1-r1:强制将所有提示消息、错误信息(包括Commands completed successfully这类severity=0的成功提示)输出到stderr,注意不要用-r0,该参数值只会捕获severity≥11的错误,会漏掉成功提示- 去掉
-o参数:Linux版sqlcmd的-o参数存在已知实现缺陷,开启后会独占stdout输出到指定文件,不会合并stderr的消息流,反而会导致shell重定向失效 2>&1:将stderr输出流合并到stdout,所有内容统一写入目标日志文件-b为可选参数,开启后SQL执行报错时sqlcmd会返回非0退出码,方便shell脚本做执行状态判断
- 如果执行后还是看不到成功提示,检查待运行的
StoredProcedure1.sql文件,在脚本最开头添加一行配置:
不少存储过程脚本会默认加SET NOCOUNT OFF;SET NOCOUNT ON配置,该配置会关闭SQL Server返回的执行行数统计、执行成功类提示消息,sqlcmd自然捕获不到对应内容。额外说明:你在SSMS里看到的Completion time行是SSMS客户端自己生成的,不是SQL Server返回的内容,sqlcmd本身不会输出这个时间戳,如果需要记录执行耗时,可以在命令前加time前缀,或者执行完成后主动追加时间到日志文件。 - 几个需要避开的常见坑:
- 不要直接套用Windows版sqlcmd的参数逻辑,Windows版
-o会自动合并所有输出流,Linux版不会 - 不要随意调整
-m错误级别参数,如果设置的阈值高于10,severity=0的成功提示会被直接过滤,保持默认不设置该参数即可 - 提前确认执行sqlcmd的用户对
/logs/目录有写权限,权限不足也会导致日志为空,按上面的命令写法,权限报错也会被捕获到日志里,方便快速排查。
- 不要直接套用Windows版sqlcmd的参数逻辑,Windows版
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

