• 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}'	'
    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 result's 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 list's 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+的工作,现在听听,觉得能力不够啊,这是这些能力也不是一天两天能掌握的,很郁闷,如果不出去,要等到什么时候,趁年轻不出去怕以后就没有机会!

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

  • 相关阅读:
    zookeeper 4 letter 描述与实践
    zookeeper理论
    Zookeeper的功能以及工作原理
    zookeeper
    VMware安装、配置CentOS
    python安装requests (win7 & centos7)
    Centos 6.4 32位 gcc 升级(已验证)
    Centos6.4编译安装Node.js(已验证)
    使用supervisor提高nodejs调试效率 (已验证)
    tar.xz文件如何解压 (已验证)
  • 原文地址:https://www.cnblogs.com/wxb0328/p/shellxml.html
Copyright © 2020-2023  润新知