问题
近期在做大数据查询引擎导出文件的功能,使用了 hive 的 beeline 客户端。发现 beeline 导出的文件以及终端输出有许多特殊字符。
按照官方文档使用 beeline 导出命令:[1]
/usr/bin/beeline --silent=true --showHeader=true --outputformat=csv2 -f query.hql </dev/null > /tmp/output.csv 2> /tmp/error.log
现象
在 vim 中显示为 ^M,在熟悉换行符的背景下,立即认出这就是 CR符号,也就是 \n
或者在excel文件头部,有很多 null,空格等符号。
分析
在做系统集成的时候,明显是不需要用 nohup的,因此没有采用文档中的写法,因为 nohup 一般直接在终端中使用;另外程序调用需要前台运行,等待结束后,获得exitCode,以及导出的文件和错误输出。
相关资料
另一位网友也遇到了这个问题[2],文章中分析了源码层面,可惜未给出合适的解决办法,但有启发。
过程
由前面的文档启发,观察 /bin/hive 脚本, 发现
if [[ "$SERVICE" =~ ^(hiveserver2|beeline|cli)$ ]] ; then# If process is backgrounded, don't change terminal settingsif [[ ( ! $(ps -o stat= -p $$) =~ "+" ) && ! ( -p /dev/stdin ) && ( ! $(ps -o tty= -p $$) =~ "?" ) ]]; thenexport HADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS -Djline.terminal=jline.UnsupportedTerminal"fi
fi
在有使用过 Alibaba Cloud Toolkit 的背景下,立即发现这是一个 stty size 的问题。
解决
在程序调用的场景下,通过/bin/bash 进行调用,所以其实是以一个终端环境,终端就涉及到美化输出的问题
所以一定要设置终端类型为不支持终端,因此显式设置变量:
HADOOP_CLIENT_OPTS="-Djline.terminal=jline.UnsupportedTerminal"ProcessBuilder _proc = new ProcessBuilder().inheritIO().command(arguments);
_proc.environment().put("HADOOP_CLIENT_OPTS","-Djline.terminal=jline.UnsupportedTerminal");
Process proc = _proc.start();
建议
一般导出的文件是UTF-8,对于Windows的用户来说,直接打开到Excel中文会乱码,最好添加上 BOM[3]。
一般添加的是EF
BB
BF
https://hive.apache.org/docs/latest/hiveserver2-clients_30758725/#background-query-in-terminal-script ↩︎
https://stefanxiepj.github.io/archives/241842c7.html ↩︎
https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-with-bom ↩︎