如何用Shell指令碼生成XML檔案
今天把這段時間學習完shell後完成工作上的一個小案件整理了一下,分享給大家!
說來也巧了,作為一個剛剛畢業半年的菜鳥,進入公司後,聽公司的大牛推薦學習linux–”鳥哥的私房菜“,基本上是從去年8月份開始到了今年的1月份,基本上是把基礎篇看完了,開始瞭解shell指令碼的相關知識。剛好公司有了一個shell指令碼的案件給我了,時間上也沒有多緊。然後就一邊學習一邊開始做,雖然中途客戶反映先前的業務邏輯有問題耽擱了兩週,但總算是到最後完成了,自己學習的東西能用到很開心,今天閒了,把程式碼整理了一下,分享給大家
具體是這樣:
要求是寫一個shell指令碼,安裝要求查詢資料,將符合條件的資料按照客戶給定的xml樣式進行組裝,然後加入到crontab中,定時執行通過scp或者ftp放到客戶伺服器上。
具體實現步驟:
一、編寫生成xml文件的程式碼
網上搜尋了一篇部落格:http://blog.csdn.net/dengzhaoqun/article/details/7262271 拿來學習了一下,感覺好用,自己就根據自己的實際情況修改了一下:
#! /bin/bash # filename: create_xml.sh # create_wangxb_20150123 # # 從外部傳入的第一個引數作為xml的檔名 outfile=$1 # xml中的縮排位 tabs=0 # ++++++++++++++++++++++++++++ # 組裝一個節點,輸出到檔案 # 說一說傳引數時的這幾個區別:假如有下面這個指令碼執行的命令 # /path/to/scriptname opt1 opt2 opt3 opt4 # $0: 的值是預設是指令碼的名字,從$1-$4 開始就是引數的值 # $# :代表後接的引數『個數』 # $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每個變數是獨立的(用雙引號括起來); # $* :代表『 "$1c$2c$3c$4" 』,其中 c 為分隔位元組,預設為空白鍵, 所以本例中代表『 "$1 $2 $3 $4" 』之意。 # 在shell中我們可以也可以使用${}包含變數名,來呼叫變數 # ++++++++++++++++++++++++++++ put(){ echo '<'${*}'>' >> $outfile } # 這裡也是輸出一個xml的節點,只是比上面的節點有更多的設定 # ${@:2} 的意思:它的值就是由第二個引數開始到最後一個引數,為什麼要這樣?有時可能你的第二個引數中有空格,shell接受引數是以空格計算的 put_tag() { echo '<'$1'>'${@:2}'</'$1'>' >> $outfile } # 同樣是一個輸出節點函式,但是新增了CDATA,防止特殊字元造成xml解析失敗 put_tag_cdata() { echo '<'$1'><![CDATA['${@:2}']]></'$1'>' >> $outfile } put_head(){ put '?'${1}'?' } # 這是一個縮排的演算法,自行理解 out_tabs(){ tmp=0 tabsstr="" while [ $tmp -lt $((tabs)) ] do tabsstr=${tabsstr}'\t' tmp=$((tmp+1)) done echo -e -n $tabsstr >> $outfile } tag_start(){ out_tabs put $1 tabs=$((tabs+1)) } tag() { out_tabs if [ "$1" == 0 ] then put_tag $2 $(echo ${@:3}) elif [ "$1" == 1 ] then put_tag_cdata $2 $(echo ${@:3}) fi } tag_end(){ tabs=$((tabs-1)) out_tabs put '/'${1} }
這裡有一些基礎知識:
關於引數:
假如有下面這個指令碼執行的命令
/path/to/scriptname opt1 opt2 opt3 opt4
$0: 的值是預設是指令碼的名字,從$1-$4 開始就是引數的值 $# :代表後接的引數『個數』 $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每個變數是獨立的(用雙引號括起來); $* :代表『 "$1c$2c$3c$4" 』,其中 c 為分隔位元組,預設為空白鍵, 所以本例中代表『 "$1 $2 $3 $4" 』之意。 在shell中我們可以也可以使用${}包含變數名,來呼叫變數
關於 ${@:2} 這種形式的說明,我轉載了一篇部落格:http://www.cnblogs.com/wxb0328/p/4276751.html
二、從資料庫查資料利用上面的函式,製作xml檔案
#!/bin/bash # filename: ts_xml.sh # create_wangxb_20150126 # 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 export PATH # Database account information file source ~/.p3src #++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # set some variable # XMLSCRIPT: 指令碼的絕對路徑 # MATCHING_RESULT_XML: xml_1的檔名 # XML_FUNC_FILE: 生成xml函式檔案路徑 # MATCHING_RESULT_QUERY_DATA: sqlplus 查出資料儲存的零時檔案 # MATCHING_RESULT_QUERY_SQL: sqlplus 查詢的sql語句 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # 下面是一些基礎的設定 export XMLSCRIPT=/usr/p3s/batch/jaaa_match/tmp_xa_wangxb XML_DIR="$XMLSCRIPT/xmldata" XML_FUNC_FILE="xml_func.sh" MATCHING_RESULT_XML="matching_result_"$(date '+%Y%m%d_%H%M%S')".xml" MATCHING_RESULT_QUERY_DATA="matching_result_query_data.tmp" MATCHING_RESULT_QUERY_SQL="matching_result_query.sql" CLIENT_LIST_XML="client_list_"$(date '+%Y%m%d_%H%M%S')".xml" CLIENT_LIST_QUERY_DATA="client_list_query_data.tmp" CLIENT_LIST_QUERY_SQL="client_list_query.sql" # add_wangxb_20150225 if [ ! -d "$XML_DIR" ]; then mkdir $XML_DIR fi #+++++++++++++++++++++++++++ # modify_wangxb_20150224 # check for temporary file #+++++++++++++++++++++++++++ if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ]; then rm -f $XML_DIR/$MATCHING_RESULT_XML fi if [ -e "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ]; then MATCHING_RESULT_QUERY_DATA="matching_result_query_data_"$(date '+%Y%m%d%H%M%S')".tmp" fi #+++++++++++++++++++++++++++++++++++++++++++++++++ # add_wangxb_20150225 # check system time, choice query time period # 這是是根據crontab每天執行的時間,取得我們查詢資料庫時的where條件的時間區間 #+++++++++++++++++++++++++++++++++++++++++++++++++ sys_datetime=$(date '+%Y%m%d%H') first_chk_datetime="$(date '+%Y%m%d')04" second_chk_datetime="$(date '+%Y%m%d')12" third_chk_datetime="$(date '+%Y%m%d')20" # 由於伺服器crontab是上面的時間,但是執行的shell比較多,在呼叫我這個shell的時候,不一定就是04:30 ,12:30, 20:30所以,這裡的根據系統的時間判斷時 範圍給的比較寬 case $sys_datetime in "$first_chk_datetime"|"$(date '+%Y%m%d')05"|"$(date '+%Y%m%d')06"|"$(date '+%Y%m%d')07") chk_start=$(date '+%Y-%m-%d 21:00:00' -d '-1 day') chk_end=$(date '+%Y-%m-%d 04:29:59') ;; "$second_chk_datetime"|"$(date '+%Y%m%d')13"|"$(date '+%Y%m%d')14"|"$(date '+%Y%m%d')15") chk_start=$(date '+%Y-%m-%d 04:30:00') chk_end=$(date '+%Y-%m-%d 12:29:59') ;; "$third_chk_datetime"|"$(date '+%Y%m%d')21"|"$(date '+%Y%m%d')22"|"$(date '+%Y%m%d')23") chk_start=$(date '+%Y-%m-%d 12:30:00') chk_end=$(date '+%Y-%m-%d 20:59:59') ;; *) chk_start=$(date '+%Y-%m-%d 00:00:00') chk_end=$(date '+%Y-%m-%d 23:59:59') ;; esac # modify_wangxb_20150310 # 下面的是做一個oracle資料庫連線的測試,如果連線失敗,後續程式碼不再執行,並且寫入錯誤日誌 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB << EOF set echo off set feedback off alter session set nls_date_format='YYYY-MM-DD:HH24:MI:SS'; select sysdate from dual; quit EOF if [ $? -ne 0 ] then echo "********** DBへのリンク己竊した **********" exit else echo "********** DBへのリンクOKです **********" fi # sqlplus就是oracle的一個客戶端軟體,具體使用方法可以問度娘,這裡傳入要執行的sql和引數,將結果 > 輸出到指定檔案 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB @$XMLSCRIPT/$MATCHING_RESULT_QUERY_SQL "$chk_start" "$chk_end" > $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA # create matching result's xml file # add_wangxb_20150227 # 下面的演算法就是將查出的資料進行分析,呼叫xml函式生成xml檔案 source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$MATCHING_RESULT_XML" put_head 'xml version="1.0" encoding="utf-8"' tag_start 'ROOT' if [ -s "$XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA" ]; then datas=${XMLSCRIPT}/${MATCHING_RESULT_QUERY_DATA} #for res in $datas while read res; do stock_id=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $1}') seirino=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $2}') match_flg=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $3}') unmatch_riyuu=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $4}') up_date_tmp=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $5}') up_date=$(echo $up_date_tmp | awk 'BEGIN {FS="@"} {print $1 " " $2}') tag_start 'MATCHING' tag 0 'STOCKID' ${stock_id:-""} tag 0 'SEIRINO' ${seirino:-""} tag 0 'RESULT' ${match_flg:-""} tag 1 'REASON' ${unmatch_riyuu:-""} tag 0 'UPDATE_DATE' ${up_date:-""} tag_end 'MATCHING' done < $datas fi tag_end 'ROOT' rm $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA # create client list's xml file # add_wangxb_2015027 # 下面的是再生成一個xml檔案,和上面一樣 if [ -e "$XML_DIR/$CLIENT_LIST_XML" ]; then rm -f $XML_DIR/$CLIENT_LIST_XML fi if [ -e "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ]; then CLIENT_LIST_QUERY_DATA="client_list_query_data_"$(date '+%Y%m%d%H%M%S')".tmp" fi $ORACLE_HOME/bin/sqlplus -s $ORAUSER_MND @$XMLSCRIPT/$CLIENT_LIST_QUERY_SQL > $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA source "$XMLSCRIPT/$XML_FUNC_FILE" "$XML_DIR/$CLIENT_LIST_XML" put_head 'xml version="1.0" encoding="utf-8"' tag_start 'ROOT' if [ -s "$XMLSCRIPT/$CLIENT_LIST_QUERY_DATA" ]; then datas=${XMLSCRIPT}/${CLIENT_LIST_QUERY_DATA} #for res in $datas while read res; do corporation_id=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $1}') corporation_name=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $2}') client_id=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $3}') client_print_name=$(echo $res | awk 'BEGIN {FS="\\^\\*\\^"} {print $4}') tag_start 'CLIENT' tag 0 'CORPORATION_ID' ${corporation_id:-""} tag 1 'CORPORATION_NAME' ${corporation_name:-""} tag 0 'CLIENT_ID' ${client_id:-""} tag 1 'CLIENT_PRINT_NAME' ${client_print_name:-""} tag_end 'CLIENT' done < $datas fi tag_end 'ROOT' rm $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA # add_wangxb_20150304 # Convert xml file encoding # 這是將xml檔案進行轉碼,命令是iconv if [ -e "$XML_DIR/$MATCHING_RESULT_XML" ]; then echo "********** matching_result.xmlファイルコ〖ドを啪垂し、**********" iconv -f euc-jp -t utf-8 $XML_DIR/$MATCHING_RESULT_XML -o $XML_DIR/$MATCHING_RESULT_XML.utf-8 mv $XML_DIR/$MATCHING_RESULT_XML.utf-8 $XML_DIR/$MATCHING_RESULT_XML fi if [ -e "$XML_DIR/$CLIENT_LIST_XML" ]; then echo "********** client_list.xmlフィルコ〖ドを啪垂し、**********" iconv -f euc-jp -t utf-8 $XML_DIR/$CLIENT_LIST_XML -o $XML_DIR/$CLIENT_LIST_XML.utf-8 mv $XML_DIR/$CLIENT_LIST_XML.utf-8 $XML_DIR/$CLIENT_LIST_XML fi # add_wangxb_20150304 # Send the xml file to the destination server by ftp #ftp_host="222.***.***.***" #USER="***" #PASS="***" #ftp -i -n $ftp_host << EOF #user $USER $PASS #cd / #lcd $XML_DIR/ #put $MATCHING_RESULT_XML #put $CLIENT_LIST_XML #quit #EOF # test ftp # 通過ftp將xml檔案放到客戶伺服器上,ftp_host:客戶伺服器地址,user登入名,pass密碼 ftp_host="***.***.***.***" USER="***" PASS="***" dir="/upload" ftp -i -n $ftp_host << EOF user $USER $PASS cd /upload/ lcd $XML_DIR/ put $MATCHING_RESULT_XML put $CLIENT_LIST_XML quit EOF # Save the program log file YYMM=$(date +'%Y%m%d%H%M') cp /tmp/create_xml.log /usr/p3s/batch/jaaa_match/tmp_xa_wangxb/logs/create_xml.log.$YYMM # Send error log files into the Admin mailbox info_to_mail_1="**@**.co.jp" info_to_mail_2="***@**.co.jp" # nkf 日文轉碼的一個命令 title=$(echo "test" | nkf -j) nkf -j < /tmp/create_xml.log | mail -s $title $info_to_mail_1 $info_to_mail_2 #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檔案
SET PAGESIZE 0 SET FEEDBACK OFF SET VERIFY OFF SET ECHO OFF SET HEADING OFF SET TIMI OFF SET LINESIZE 1000 SET WRAP OFF 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; exit
SET PAGESIZE 0 SET FEEDBACK OFF SET VERIFY OFF SET ECHO OFF SET HEADING OFF SET TIMI OFF SET LINESIZE 1000 SET WRAP OFF 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; exit
三、來看看效果
當然中間出現了許多bug,不過慢慢修改嗎,兵來將擋,水來土掩,bug來了自己調麼
就這樣簡單的整理一下,可能光這麼寫不夠完整,但是,中間設計的知識也很多,不能展開了說,做個分享,大家有用到的時候也是個思路,具體的某些知識點可以用到了再去找資料了。
相關文章
- [Shell] Shell 生成 HTML指令碼HTML指令碼
- Shell指令碼 | 抓取log檔案指令碼
- 巧用shell指令碼生成快捷指令碼指令碼
- shell指令碼之批次清空檔案指令碼
- 使用shell指令碼巧妙統計檔案指令碼
- shell指令碼技巧—建立和清空檔案指令碼
- Oracle通過Sqlplus結合Shell指令碼方式生成Excel檔案OracleSQL指令碼Excel
- [ Shell ] 通過 Shell 指令碼匯出 GDSII/OASIS 檔案指令碼
- shell指令碼0——”一切皆檔案“, 認識Shell指令碼
- 共享一個iptables的shell指令碼檔案指令碼
- Shell指令碼逐行處理文字檔案技巧指令碼
- shell 備份檔案指令碼+自動清理指令碼
- 【shell 】求兩個檔案相加的指令碼指令碼
- 利用shell指令碼生成動態sql指令碼SQL
- [Shell] Shell 生成 HTML指令碼,可顯示錶格HTML指令碼
- vbs類生成xml檔案(轉)XML
- 如何在Shell指令碼中逐行讀取檔案指令碼
- 使用shell指令碼build並建立ipa檔案(轉)指令碼UI
- 【shell 指令碼】檢視*.gz 檔案的內容指令碼
- Linux/Unix shell 指令碼清除歸檔日誌檔案Linux指令碼
- 第22篇 生成proto檔案bat指令碼BAT指令碼
- 案例四:Shell指令碼生成隨機密碼指令碼隨機密碼
- Linux shell格式化XML檔案LinuxXML
- Python解析XML檔案生成HTMLPythonXMLHTML
- 使用shell指令碼生成只讀許可權的sql指令碼指令碼SQL
- 如何讓shell指令碼變成可執行檔案指令碼
- 用shell指令碼合併多個檔案內容指令碼
- 建立定期清理listener,trace檔案的shell指令碼指令碼
- PowerDesigner: 利用sql指令碼檔案逆生成模型SQL指令碼模型
- 巧用shell生成資料庫檢查指令碼資料庫指令碼
- 使用shell生成orabbix自動化配置指令碼指令碼
- 如何在shell指令碼里使用sftp批次傳送檔案指令碼FTP
- shell指令碼自動清理超過指定大小的檔案指令碼
- shell指令碼——比較兩個檔案大小、許可權指令碼
- 將DOS批處理檔案轉換為Shell指令碼指令碼
- shell指令碼之刪除固定天數之前的檔案指令碼
- 使用shell指令碼替換csv檔案中的資料指令碼
- shell指令碼實現自動生成awr報告指令碼