当通过dbaccess可执行文件使用informix数据库的转储时,我遇到了一个非常奇怪的问题。
以下是问题的表现:
~ # echo "unload to /dev/stdout [ select statement ]" | dbaccess db 2>/dev/null
H300|1|
~ # 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
~ # 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
~ #
正确的输出是"0";H300|1|";但当我重定向时,我会得到一些奇怪的东西。我怀疑dbaccess可执行文件向stdout写入的内容会干扰同样写入同一文件(/dev/stdout(的转储。
卸载到与stdout不同的文件会产生以下输出:
~ # cat not_stdout
H300|1|
~ # hexdump -C not_stdout
00000000 48 33 30 30 7c 31 7c 0a |H300|1|.|
00000008
~ #
注意:如果我使用gzip-c,那么输出的gzip文件包含有效的数据,没有丢失字符,就像输入一样。
数据库设置:
~ # 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
~ #
在具有相同行为的操作系统上运行:
test_shell:cat /etc/SUSE-brand
SLE
VERSION = 15
test_shell:uname -a
Linux test-linux 5.3.18-22-default #1 SMP Wed Jun 3 12:16:43 UTC 2020 (720aeba) x86_64 x86_64 x86_64 GNU/Linux
test_shell:
test_shell2:/home/# cat /etc/SuSE-release
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 4
test_shell2:/home/# uname -a
Linux test-linux 3.0.101-63-default #1 SMP Tue Jun 23 16:02:31 UTC 2015 (4b89d0c) x86_64 x86_64 x86_64 GNU/Linux
test_shell2:/home/# cat /etc/SuSE-brand
SLES
VERSION = 11
CO-BRANDS = SLE openSUSE
test_shell2:/home/#
因此,在SLES15SP2和SLES11SP4上都会发生这种情况。我可以简单地使用cat/tee技巧或gzip-c来完成我的工作,但如果可能的话,我只想得到一个解释。
在我的案例中,解决方案是这样使用grep(我将立即解释|| true
的原因。
echo "unload to /dev/stdout delimiter '|' [ select statement ]" | dbaccess db 2>/dev/null | (grep '|' || true)
我做了一个grep,只包含一些数据的行(只要"|"用作分隔符即可。
我使用|| true
来确保管道中的命令没有一个失败,因为我在bash中使用${PIPESTATUS[@]}
来验证它们。
除非其他人在合理的时间内对此做出解释,否则我不会选择这个答案作为正确答案。
如前所述,我已经解决了这个问题,并记录了所有内容。