运维人员面对的环境是复杂的。仅就操作系统而言,就有Windows Server、Unix、AIX和各种分支服务器OS。由于系统环境的差异,运维人员是很难做到知识面面俱到,对所有的特性了如指掌。这个时候,个人发展的方向性和坚持精神就十分重要。一点点的积累,从一些小问题着手,个人才能慢慢的成长。
AIX/Linux和Windows在体系架构、文件系统等方面的差异多如牛毛。本篇从一个执行错误的shell脚本入手,讨论一个简单的文本差异特性。
1、问题出现
一个同事在编写备份Shell脚本时,遇到了报错信息如下。
报错是比较奇怪的。脚本命令是参考现成执行脚本编写的,不会有过多的语法语义错误。更有甚者,一些报错行(如22、26)脚本中都是空行。空行为什么会出现报错信息?
2、文本结尾差异
这种情况,通常是遇到了文本行结尾差异问题。ASCII格式是我们非常常用的格式类型。从Linux中大量配置文件,到各类型应用系统的日志文件,我们都可以看到ASCII格式文本的身影。
经常使用AIX/Unix环境的朋友可能会有这样的经历:如果我们将AIX/Unix环境创建的文件传递到Windows平台,使用“记事本”软件打开,就会发现所有的换行标记都转化为黑点,而且换行数据全部被设定为一行。
解决这种混乱,比较好的方法是使用专业的工具如UlterEdit或者写字板打开,换行标记可以识别正确。
究其原因,本质上是由于两种操作系统平台对于换行标记差异造成的。在Unix/AIX中,换行标记是Line Feed(也就是经常出现的LF)。而在Windows环境中,换行回车标记为一个Line Feed外加一个Carriage Return(CR)。无论是LF还是CR,都反映在ASCII格式的文件字符中。
在很多情况下,换行字符是文件进行跨平台经常出故障的地方。如果我们在Windows环境下保存一个文本文件,那么拿到AIX/Unix环境下,读取过程就会出现一个多余的^M字符,从而报错。这也就是同事遇到问题的本质原因。
经过询问,同事脚本的确进行过Windows环境的编辑保存动作。并且是使用默认的记事本报错。
那么,如何处理这样的问题呢?
3、Utl_File输出的文件回车符
聊解决办法之前,我们先看看PL/SQL程序包utl_file。程序UTL_FILE历史很久,可以追溯到早期的Oracle版本。UTL_FILE用于在Server端指定目录上输出ASCII格式文本。其性能和简单特性给很多应用程序提供了文件输出接口。
那么,Utl_file在换行符问题上,是如何处理的呢?Oracle这里采用的策略是“随行就市”。不同的操作系统平台,put_line的时候生成不同换行标记。下面我们做一个小实验,来证明这点。实验Oracle 11gR2测试。
SQL> select * from v$version;
BANNER
----------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 – Production
创建directory和PL/SQL脚本片段。
SQL> create directory file_dir as '/tmp';
Directory created
SQL> declare
2 file_info utl_file.file_type;
3 begin
4 file_info := utl_file.fopen('FILE_DIR','test.log','w');
5 utl_file.put_line(file_info,'This is line 1');
6 utl_file.put_line(file_info,'This is line 2');
7 utl_file.put_line(file_info,'This is line 3');
8 utl_file.fclose(file_info);
9 end;
10 /
PL/SQL procedure successfully completed
从Linux环境中,我们可以看到正确的换行数据。
[oracle@SimpleLinux tmp]$ pwd
/tmp
[oracle@SimpleLinux tmp]$ ls -l | grep test
-rw-r--r-- 1 oracle oinstall 45 Jan 10 10:52 test.log
[oracle@SimpleLinux tmp]$ cat test.log
This is line 1
This is line 2
This is line 3
但是我们使用FTP/SFTP将原来文件下载到Windows本地,使用记事本软件打开文本,发现换行符问题。
说明,在utl_file输出文件的时候,是按照Server端的环境配置来设置换行信息的。如果我们在Windows服务器上执行,想必也是Windows的换行方式。
这也引起了一个问题,我们使用utl_file包生成接口文件,是在一定的操作系统平台基础上。如果是Linux/AIX生成的文件,那么接收方一定也要是Linux/AIX环境才能正确接受。注意:一些文献中声称使用ASCII格式FTP传输文件,可以实现换行符的自动切换。这样是比较方便的,但是笔者没有测试成功。
在Windows平台上,遇到这样的问题,我们是使用UltreEdit等编辑器软件保存为Unix换行标记才行。在Linux平台上,有一些命令可以帮助我们这种转换。
4、unix2dos和dos2unix
在Linux中,特别提供了配对命令工具unix2dos和dos2unix,用于进行两种格式的转换。
Unix2dos用于将Unix格式转化为Windows格式,其中的回车符也是支持转换的。使用我们之前创建的test.log文件。
[oracle@SimpleLinux tmp]$ unix2dos test.log
unix2dos: converting file test.log to DOS format ...
换行符正常,拷贝到Windows环境中查看。
同理dos2unix可以实现从dos格式转化为unix。针对我们的程序脚本,进行处理。
[oracle@SimpleLinux tmp]$ dos2unix hot_xxx_change2.sh
dos2unix: converting file hot_xxx_change2.sh to UNIX format ...
[oracle@SimpleLinux tmp]$
到windows环境上,我们可以看到这种变化。
试验成功。
5、结论
字符集是无论运维还是开发都不容易处理、而且不能避免的老问题。通过这个案例,我们了解了Oracle和操作系统回车字符的特点和功能差异,记录下来,供有需要的朋友不时之需。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-1070126/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-1070126/