重定向Informix的dbaccess导出输出时出现字符丢失问题
Informix dbaccess导出到stdout时重定向丢字符问题
问题现象
我在通过dbaccess可执行程序导出Informix数据库的数据时遇到异常,具体测试现象如下:
直接输出到终端时结果正常:
~ # echo "unload to /dev/stdout [ select statement ]" | dbaccess db 2>/dev/null H300|1|
通过管道传给hexdump查看也能得到完整结果:
~ # echo "unload to /dev/stdout [ select statement ]" | dbaccess db 2>/dev/null | hexdump -C 00000000 48 33 30 30 7c 31 7c 0a 0a |H300|1|..| 00000009
但直接重定向到文件时,首字符H丢失,头部多了一个换行:
~ # echo "unload to /dev/stdout [ select statement ]" | dbaccess db 2>/dev/null > redir ~ # cat redir 300|1| ~ # hexdump -C redir 00000000 0a 33 30 30 7c 31 7c 0a |.300|1|.| 00000008
如果将unload目标指定为stdout之外的普通文件,输出完全正常:
~ # cat not_stdout H300|1| ~ # hexdump -C not_stdout 00000000 48 33 30 30 7c 31 7c 0a |H300|1|.| 00000008
另外还有一个特殊现象:如果输出通过gzip -c压缩后再重定向,解压后的结果完整无丢失,符合预期。
环境信息
数据库版本
~ # echo "SELECT DBINFO('version', 'full') FROM \"informix\".systables WHERE tabid = 1" | dbaccess sysuser Database selected. (constant) IBM Informix Dynamic Server Version 11.50.FC9W3 1 row(s) retrieved. Database closed. ~ # dbaccess -version Program Name: dbaccess Build Version: 11.50.FC9W3 Build Number: N014 Build Host: vidar Build OS: Linux 2.6.9-34.ELsmp Build Date: Fri Mar 29 08:40:42 CDT 2013 GLS Version: glslib-4.50.FC12 ~ # dbaccess -V DB-Access Version 11.50.FC9W3 Software Serial Number AAA#B000000
复现操作系统
- SUSE Linux Enterprise 15 x86_64,内核版本5.3.18-22-default
- SUSE Linux Enterprise Server 11 SP4 x86_64,内核版本3.0.101-63-default
目前已经可以通过cat/tee中转、或者gzip -c处理的方式规避问题,但需要明确问题的根本原因。
问题解答
这个问题是11.50版本Informix的dbaccess工具的固有实现缺陷,核心原因如下:
- dbaccess本身的输出逻辑设计问题:当stdout是终端设备时,dbaccess默认会先输出少量控制字符或者空白换行做终端初始化,之后unload指令写入
/dev/stdout的内容会追加在后面输出到终端,你看到的正常结果实际上是控制字符被终端自动忽略了,所以没显示出来。 - 当stdout是普通文件(即重定向场景)时,dbaccess的初始化输出和unload写入
/dev/stdout的内容是两个独立的写入操作,两个操作共用同一个文件偏移指针:dbaccess先写入了一个换行符,偏移走到第1位,之后unload往/dev/stdout写数据时,会覆盖从偏移1开始的位置,所以首字符H被后续的换行覆盖了,就出现了你看到的结果。 - 当stdout是管道(比如传给hexdump、gzip、tee的时候),管道是流式设备没有偏移指针,两个写入的内容会按顺序拼接,所以gzip压缩后内容完整,传给hexdump也能看到完整的字符+额外换行。
- 你直接unload到普通文件时,数据是直接写入目标文件,和dbaccess自身的stdout输出完全分开,所以不会有冲突。
这个问题在后续的Informix 12.10及以上版本中已经被修复,对于11.50版本你现在用的tee/cat中转、或者直接unload到临时文件再读取的方案都是稳定可行的。
内容的提问来源于stack exchange,提问作者INS
相关产品推荐
相关产品推荐

