shell脚本生成xml文件

  今天把这段时间学习完shell后完成工作上的一个小案件整理了一下,分享给大家!

  说来也巧了,作为一个刚刚毕业半年的菜鸟,进入公司后,听公司的大牛推荐学习linux--”鸟哥的私房菜“,基本上是从去年8月份开始到了今年的1月份,基本上是把基础篇看完了,开始了解shell脚本的相关知识。刚好公司有了一个shell脚本的案件给我了,时间上也没有多紧。然后就一边学习一边开始做,虽然中途客户反映先前的业务逻辑有问题耽搁了两周,但总算是到最后完成了,自己学习的东西能用到很开心,今天闲了,把代码整理了一下,分享给大家

  具体是这样:

  要求是写一个shell脚本,安装要求查询数据,将符合条件的数据按照客户给定的xml样式进行组装,然后加入到crontab中,定时执行通过scp或者ftp放到客户服务器上。

  具体实现步骤:

  一、编写生成xml文档的代码

     网上搜索了一篇博客:http://blog.csdn.net/dengzhaoqun/article/details/7262271   拿来学习了一下,感觉好用,自己就根据自己的实际情况修改了一下:

 1 #! /bin/bash
 2 # filename: create_xml.sh
 3 # create_wangxb_20150123
 4 #
 5 # 从外部传入的第一个参数作为xml的文件名
 6 outfile=$1
 7 # xml中的缩进位
 8 tabs=0
 9 
10 # ++++++++++++++++++++++++++++
11 # 组装一个节点,输出到文件
12 # 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
13 # /path/to/scriptname  opt1  opt2  opt3  opt4 
14 # $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
15 # $# :代表后接的参数『个数』
16 # $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来); 
17 # $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
18 # 在shell中我们可以也可以使用${}包含变量名,来调用变量
19 # ++++++++++++++++++++++++++++
20 put(){
21     echo <${*}> >> $outfile
22 }
23 
24 # 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
25 # ${@:2} 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
26 put_tag() {
27     echo <$1>${@:2}</$1> >> $outfile
28 }
29 # 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
30 put_tag_cdata() {
31     echo <$1><![CDATA[${@:2}]]></$1> >> $outfile
32 }
33 
34 put_head(){
35     put ?${1}?
36 }
37 # 这是一个缩进的算法,自行理解
38 out_tabs(){
39     tmp=0
40     tabsstr=""
41     while [ $tmp -lt $((tabs)) ]
42     do
43         tabsstr=${tabsstr}\t
44         tmp=$((tmp+1))
45     done
46     echo -e -n $tabsstr >> $outfile
47 }
48 
49 tag_start(){
50     out_tabs
51     put $1
52     tabs=$((tabs+1))
53 }
54 
55 tag() {
56     out_tabs
57     if [ "$1" == 0 ]
58     then
59         put_tag $2 $(echo ${@:3})
60     elif [ "$1" == 1 ]
61     then
62         put_tag_cdata $2 $(echo ${@:3})
63     fi
64 }
65 
66 tag_end(){
67     tabs=$((tabs-1))
68     out_tabs
69     put /${1}
70 }

  这里有一些基础知识: 

  关于参数:

  假如有下面这个脚本执行的命令
     /path/to/scriptname opt1 opt2 opt3 opt4
   

1 $0: 的值是默认是脚本的名字,从$1-$4 开始就是参数的值
2 $# :代表后接的参数『个数』
3 $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来); 
4 $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
5 在shell中我们可以也可以使用${}包含变量名,来调用变量

 

  关于 ${@:2} 这种形式的说明,我转载了一篇博客:http://www.cnblogs.com/wxb0328/p/4276751.html

 

  二、从数据库查数据利用上面的函数,制作xml文件

  1 #!/bin/bash
  2 # filename: ts_xml.sh
  3 # create_wangxb_20150126
  4 #
  5 
  6 PATH=/u01/app/oracle/product/10.2.0/db_1/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/dell/srvadmin/bin:/home/p3s_batch/tools:/home/p3s_batch/bin
  7 export PATH
  8 # Database account information file
  9 source ~/.p3src
 10 
 11 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 12 # set some variable 
 13 # XMLSCRIPT: 脚本的绝对路径
 14 # MATCHING_RESULT_XML: xml_1的文件名 
 15 # XML_FUNC_FILE: 生成xml函数文件路径
 16 # MATCHING_RESULT_QUERY_DATA: sqlplus 查出数据保存的零时文件
 17 # MATCHING_RESULT_QUERY_SQL: sqlplus 查询的sql语句
 18 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 19 # 下面是一些基础的设置
 20 export XMLSCRIPT=/usr/p3s/batch/jaaa_match/tmp_xa_wangxb
 21 XML_DIR="$XMLSCRIPT/xmldata"
 22 XML_FUNC_FILE="xml_func.sh"
 23 
 24 MATCHING_RESULT_XML="matching_result_"$(date +%Y%m%d_%H%M%S)".xml"
 25 MATCHING_RESULT_QUERY_DATA="matching_result_query_data.tmp"
 26 MATCHING_RESULT_QUERY_SQL="matching_result_query.sql"
 27 
 28 CLIENT_LIST_XML="client_list_"$(date +%Y%m%d_%H%M%S)".xml"
 29 CLIENT_LIST_QUERY_DATA="client_list_query_data.tmp"
 30 CLIENT_LIST_QUERY_SQL="client_list_query.sql"
 31 
 32 # add_wangxb_20150225
 33 if [ ! -d "$XML_DIR" ];
 34 then
 35     mkdir $XML_DIR
 36 fi
 37 
 38 #+++++++++++++++++++++++++++
 39 # modify_wangxb_20150224
 40 # check for temporary file 
 41 #+++++++++++++++++++++++++++
 42 if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ];
 43 then
 44     rm -f $XML_DIR/$MATCHING_RESULT_XML
 45 fi
 46 
 47 if [ -e "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ];
 48 then
 49     MATCHING_RESULT_QUERY_DATA="matching_result_query_data_"$(date +%Y%m%d%H%M%S)".tmp"
 50 fi
 51 #+++++++++++++++++++++++++++++++++++++++++++++++++
 52 # add_wangxb_20150225
 53 # check system time,  choice query time period
 54 # 这是是根据crontab每天执行的时间,取得我们查询数据库时的where条件的时间区间
 55 #+++++++++++++++++++++++++++++++++++++++++++++++++
 56 sys_datetime=$(date +%Y%m%d%H)
 57 first_chk_datetime="$(date ‘+%Y%m%d‘)04"
 58 second_chk_datetime="$(date ‘+%Y%m%d‘)12"
 59 third_chk_datetime="$(date ‘+%Y%m%d‘)20"
 60 # 由于服务器crontab是上面的时间,但是执行的shell比较多,在调用我这个shell的时候,不一定就是04:3012:30, 20:30所以,这里的根据系统的时间判断时 范围给的比较宽
 61 case $sys_datetime in
 62     "$first_chk_datetime"|"$(date ‘+%Y%m%d‘)05"|"$(date ‘+%Y%m%d‘)06"|"$(date ‘+%Y%m%d‘)07")
 63         chk_start=$(date +%Y-%m-%d 21:00:00 -d -1 day)
 64         chk_end=$(date +%Y-%m-%d 04:29:59)
 65     ;;
 66     "$second_chk_datetime"|"$(date ‘+%Y%m%d‘)13"|"$(date ‘+%Y%m%d‘)14"|"$(date ‘+%Y%m%d‘)15")
 67         chk_start=$(date +%Y-%m-%d 04:30:00)
 68         chk_end=$(date +%Y-%m-%d 12:29:59)
 69 
 70     ;;
 71     "$third_chk_datetime"|"$(date ‘+%Y%m%d‘)21"|"$(date ‘+%Y%m%d‘)22"|"$(date ‘+%Y%m%d‘)23")
 72         chk_start=$(date +%Y-%m-%d 12:30:00)
 73         chk_end=$(date +%Y-%m-%d 20:59:59)
 74 
 75     ;;
 76     *)
 77         chk_start=$(date +%Y-%m-%d 00:00:00)
 78         chk_end=$(date +%Y-%m-%d 23:59:59)
 79 
 80     ;;
 81 esac
 82 
 83 # modify_wangxb_20150310
 84 # 下面的是做一个oracle数据库连接的测试,如果连接失败,后续代码不再执行,并且写入错误日志
 85 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB << EOF
 86 set echo off
 87 set feedback off
 88 alter session set nls_date_format=YYYY-MM-DD:HH24:MI:SS;
 89 select sysdate from dual;
 90 quit
 91 EOF
 92 if [ $? -ne 0 ]
 93 then 
 94     echo "********** DBへのリンク己窃した **********"
 95     exit
 96 else
 97     echo "********** DBへのリンクOKです **********"
 98 fi
 99 # sqlplus就是oracle的一个客户端软件,具体使用方法可以问度娘,这里传入要执行的sql和参数,将结果 > 输出到指定文件
100 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB @$XMLSCRIPT/$MATCHING_RESULT_QUERY_SQL "$chk_start" "$chk_end" > $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA
101 
102 
103 # create matching results xml file
104 # add_wangxb_20150227
105 # 下面的算法就是将查出的数据进行分析,调用xml函数生成xml文件
106 source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$MATCHING_RESULT_XML"
107 put_head xml version="1.0" encoding="utf-8"
108 tag_start ROOT
109 if [ -s "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ];
110 then
111     datas=${XMLSCRIPT}/${MATCHING_RESULT_QUERY_DATA}
112     #for res in $datas
113     while read res;
114     do
115         stock_id=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $1})
116         seirino=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $2})
117         match_flg=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $3})
118         unmatch_riyuu=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $4})
119         up_date_tmp=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $5})
120         up_date=$(echo $up_date_tmp | awk BEGIN {FS="@"} {print $1 " " $2})
121         tag_start MATCHING
122         tag 0 STOCKID ${stock_id:-""}
123         tag 0 SEIRINO ${seirino:-""}
124         tag 0 RESULT ${match_flg:-""}
125         tag 1 REASON ${unmatch_riyuu:-""}
126         tag 0 UPDATE_DATE ${up_date:-""}
127         tag_end MATCHING
128     done < $datas
129 fi
130 tag_end ROOT
131 rm $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA
132 
133 
134 # create client lists xml file
135 # add_wangxb_2015027
136 # 下面的是再生成一个xml文件,和上面一样
137 if [ -e "$XML_DIR/$CLIENT_LIST_XML" ];
138 then
139     rm -f $XML_DIR/$CLIENT_LIST_XML
140 fi
141 
142 if [ -e "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ];
143 then
144     CLIENT_LIST_QUERY_DATA="client_list_query_data_"$(date +%Y%m%d%H%M%S)".tmp"
145 fi
146 
147 
148 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_MND @$XMLSCRIPT/$CLIENT_LIST_QUERY_SQL > $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA
149 
150 source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$CLIENT_LIST_XML"
151 put_head xml version="1.0" encoding="utf-8"
152 tag_start ROOT
153 if [ -s "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ];
154 then
155     datas=${XMLSCRIPT}/${CLIENT_LIST_QUERY_DATA}
156     #for res in $datas
157     while read res;
158     do
159         corporation_id=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $1})
160         corporation_name=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $2})
161         client_id=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $3})
162         client_print_name=$(echo $res | awk BEGIN {FS="\\^\\*\\^"} {print $4})
163         tag_start CLIENT
164         tag 0 CORPORATION_ID ${corporation_id:-""}
165         tag 1 CORPORATION_NAME ${corporation_name:-""}
166         tag 0 CLIENT_ID ${client_id:-""}
167         tag 1 CLIENT_PRINT_NAME ${client_print_name:-""}
168         tag_end CLIENT
169     done < $datas
170 fi
171 tag_end ROOT
172 rm $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA
173 
174 
175 # add_wangxb_20150304
176 # Convert xml file encoding
177 # 这是将xml文件进行转码,命令是iconv
178 if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ];
179 then
180     echo "********** matching_result.xmlファイルコ〖ドを啪垂し、**********"
181     iconv -f euc-jp -t utf-8 $XML_DIR/$MATCHING_RESULT_XML  -o $XML_DIR/$MATCHING_RESULT_XML.utf-8
182     mv $XML_DIR/$MATCHING_RESULT_XML.utf-8 $XML_DIR/$MATCHING_RESULT_XML
183 fi
184 if [ -e "$XML_DIR/$CLIENT_LIST_XML" ];
185 then
186     echo "********** client_list.xmlフィルコ〖ドを啪垂し、**********"
187     iconv -f euc-jp -t utf-8 $XML_DIR/$CLIENT_LIST_XML  -o $XML_DIR/$CLIENT_LIST_XML.utf-8
188     mv $XML_DIR/$CLIENT_LIST_XML.utf-8 $XML_DIR/$CLIENT_LIST_XML
189 fi
190 
191 # add_wangxb_20150304
192 # Send the xml file to the destination server by ftp
193 #ftp_host="222.***.***.***"
194 #USER="***"
195 #PASS="***"
196 #ftp -i -n $ftp_host << EOF
197 #user $USER $PASS
198 #cd /
199 #lcd $XML_DIR/
200 #put $MATCHING_RESULT_XML
201 #put $CLIENT_LIST_XML
202 #quit
203 #EOF
204 
205 # test ftp
206 # 通过ftp将xml文件放到客户服务器上,ftp_host:客户服务器地址,user登录名,pass密码
207 ftp_host="***.***.***.***"
208 USER="***"
209 PASS="***"
210 dir="/upload"
211 ftp -i -n $ftp_host << EOF
212 user $USER $PASS
213 cd /upload/
214 lcd $XML_DIR/
215 put $MATCHING_RESULT_XML
216 put $CLIENT_LIST_XML
217 quit
218 EOF
219 
220 
221 # Save the program log file
222 YYMM=$(date +%Y%m%d%H%M)
223 cp /tmp/create_xml.log /usr/p3s/batch/jaaa_match/tmp_xa_wangxb/logs/create_xml.log.$YYMM
224 
225 # Send error log files into the Admin mailbox
226 info_to_mail_1="**@**.co.jp"
227 info_to_mail_2="***@**.co.jp"
228 # nkf 日文转码的一个命令
229 title=$(echo "test" | nkf -j)
230 nkf -j < /tmp/create_xml.log | mail -s $title $info_to_mail_1 $info_to_mail_2
231 
232 
233 #exit

  关于nkf 日文转码:http://www.cnblogs.com/wxb0328/p/4333820.html

  本来是用scp传送的,但是后面修改了,这里把自己为scp传送找到的一个,不用密码可立即登入的 ssh 用户

  在鸟哥私房菜的服务器架设篇的第十一章中有介绍:http://vbird.dic.ksu.edu.tw/linux_server/0310telnetssh_2.php#ssh_nopasswd

  下面是执行的两个sql文件

 1 SET PAGESIZE 0
 2 SET FEEDBACK OFF
 3 SET VERIFY OFF
 4 SET ECHO OFF
 5 SET HEADING OFF
 6 SET TIMI OFF
 7 SET LINESIZE 1000
 8 SET WRAP OFF
 9 
10 
11 SELECT s.STOCKID|| ^*^ ||a.SERI_NO|| ^*^ ||a.MATCH_FLG|| ^*^ ||a.UNMATCH_RIYUU|| ^*^ ||to_char(a.UP_DATE,YYYY-MM-DD@HH24:MI:SS) UP_DATE FROM aaa_stock_db a LEFT JOIN SENDDATAAPPRAISALPROTO s ON a.SERI_NO=s.SEIRINO WHERE a.UP_DATE BETWEEN to_date(&1,yyyy-mm-dd hh24:mi:ss) AND to_date(&2,yyyy-mm-dd hh24:mi:ss) AND a.DEL_FLG=0 ORDER BY a.UP_DATE DESC;
12 
13 exit
 1 SET PAGESIZE 0
 2 SET FEEDBACK OFF
 3 SET VERIFY OFF
 4 SET ECHO OFF
 5 SET HEADING OFF
 6 SET TIMI OFF
 7 SET LINESIZE 1000
 8 SET WRAP OFF
 9 
10 
11 SELECT a.CORPORATION_ID|| ^*^ ||a.CORPORATION_NAME|| ^*^ ||b.CLIENT_ID|| ^*^ ||(select CLIENT_PRINT_NAME from CLIENT_MASTER where CLIENT_ID = b.CLIENT_ID) as CLIENT_PRINT_NAME FROM M_CORPORATION_MASTER a LEFT JOIN M_CORPORATION_GROUP b ON (a.CORPORATION_ID = b.CORPORATION_ID) WHERE a.DEL_FLG=0 AND b.DEL_FLG=0;
12 
13 exit

  

  三、来看看效果

    当然中间出现了许多bug,不过慢慢修改吗,兵来将挡,水来土掩,bug来了自己调么

 技术分享

  

  就这样简单的整理一下,可能光这么写不够完整,但是,中间设计的知识也很多,不能展开了说,做个分享,大家有用到的时候也是个思路,具体的某些知识点可以用到了再去找资料了

  题外话:

  这几天打算辞职,想去外面,但是听了在外面找工作的同学说,外面要求的技术很多:“什么优化,缓存,环境搭建啊,高并发,读写分离,负载均衡等等”  。突然就没有了去外面的激情,而且毕竟才毕业半年,工资也不高,毕业前出去旅行也借了5K的钱都没有还,哎、、、本来想着去深圳,怎么也能找个6K+的工作,现在听听,觉得能力不够啊,这是这些能力也不是一天两天能掌握的,很郁闷,如果不出去,要等到什么时候,趁年轻不出去怕以后就没有机会!

  哎、、、这个决定该怎么做,有点烦!如果哪位大牛能够看到小弟这篇博客,希望能提点建设性的意见,不胜感激!!涕泗横流!!!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。