初试Shell脚本
背景
臨上線前測(cè)試比較努力,遇到閃退或者其他問題,會(huì)把日志包打給我,由于app內(nèi)存限制,目前每次打包都是1m大小,所以有時(shí)查找問題的上下文比較吃力。同時(shí)由于日志比較多,根據(jù)關(guān)鍵詞過濾的需求越來越重要。
于是決定學(xué)寫腳本完成這個(gè)任務(wù),根據(jù)我的要求,工作流程應(yīng)該是傳入壓縮包,根據(jù)后綴名解壓,根據(jù)日期排序后合并成一個(gè)文件,按需過濾關(guān)鍵詞。
先上代碼
#!/usr/bin/env bash # Created By Vanch at 2018/9/20printHelp() {echo "Uncompess log files from inputed zip"echo "Then Merge these logs to one file"echo "Supported file types: zip tar tar.gz tar.bz2"echoecho "Use -s for filtering socket result to socket.log"echo echo "Have fun!" }#如果沒輸入?yún)?shù),就打印幫助信息 if [ $# -eq 0 ]; thenprintHelpexit 0 fi#把長(zhǎng)選項(xiàng)轉(zhuǎn)到短選項(xiàng) for arg in "$@"; doshiftcase "$arg" in"--help") set -- "$@" "-h" ;;"--version") set -- "$@" "-v" ;;"--list") set -- "$@" "-l" ;;*) set -- "$@" "$arg"esac done #獲取短選項(xiàng) OPTIND=1 printS=false; while getopts "dmksahvl" opt; docase $opt inh) #輸入為help,就打印幫助信息printHelpexit 0;;l) #支持單獨(dú)獲取支持文件后綴列表echo "Supported file types: zip tar tar.gz tar.bz2"exit 0;;v) #支持查找版本號(hào)echo "1.0.0"exit 0;;s) #過濾SocketprintS=true;;esac done#獲得壓縮包地址 file=${!#} #如果不存在就退出 if [ ! -f "$file" ]; thenecho "File not exist!"exit 0; fi #獲取壓縮后綴 fileName=`basename $file` suffix=${fileName#*.} #判斷文件類型 support=('tar','tar.gz','tar.bz2','zip') if [ -z `echo "${support[@]}" | grep -w "$suffix"` ] ; thenecho "File type not support!"exit 0; fi #拼接文件夾地址 fileDir=$(dirname $file)/${fileName%%.*} if [ -d $fileDir ]; thenrm -rf $fileDir fi mkdir $fileDir cd $fileDir #解壓文件 case $suffix in'tar')eval "tar xvf $file > /dev/null 2>&1";;'tar.gz')eval "tar zxvf $file > /dev/null 2>&1";;'tar.bz2')eval "tar jxvf $file > /dev/null 2>&1";;'zip')eval "unzip -o $file > /dev/null 2>&1";; esac echo 'Uncompass Success!'#獲取日志列表,按排序合并到一個(gè)日志 mergeFile=./merge.log logCount=0 #搜索com開頭的日志,按日期排序,用?臨時(shí)代替空格 for logName in `ls | grep 'com' | sort -n | tr " " "?"`; dologName=${logName//'?'/' '}cat ./"$logName" >> $mergeFile((logCount++)) done #不存在日志就打斷 if [ $logCount -eq 0 ]; thenecho "Log not exist!"exit fi echo 'Merge Success!' #打印socket if [ $printS = true ]; thencat $mergeFile | grep -i 'socket' >> ./socket.logecho 'Filter socket' fi遇到的問題
查詢了很多資料后寫完了這個(gè)腳本,基本滿足了我的需求,下面總結(jié)一下怎么解決遇到的問題。
使用環(huán)境
一開始學(xué)腳本時(shí),書上都說#! /bin/bash,但是看項(xiàng)目中大神寫的腳本,都是#!/usr/bin/env bash,有什么區(qū)別呢?
腳本用env啟動(dòng)的原因,是因?yàn)槟_本解釋器在linux中可能被安裝于不同的目錄,env可以在系統(tǒng)的PATH目錄中查找。
同時(shí),env還規(guī)定一些系統(tǒng)環(huán)境變量。
不同的系統(tǒng),解釋器的路徑可能也不同,所以使用絕對(duì)路徑是比較危險(xiǎn)的方式。通過從環(huán)境中查找,可以保證兼容性。
獲取選項(xiàng)
開發(fā)中我們經(jīng)常用到命令,這些命令一般都配合選項(xiàng)達(dá)到不同的效果,比如最常用的ls -al,通過-a來指定結(jié)果包含隱藏文件,通過-l達(dá)到列表顯示的效果。
通過查詢相關(guān)資料,我發(fā)現(xiàn)獲取選項(xiàng)普遍的做法是使用getopts命令,但是這個(gè)方法只能獲取-h這種短選項(xiàng),對(duì)于--help長(zhǎng)選項(xiàng)就不行。
第一種辦法是換成getopt命令,但是并不是每個(gè)系統(tǒng)都支持這個(gè)命令。具體使用和getopts類似,比如getopt -o ab:c -l a-long:b-long
第二種方法是把支持的長(zhǎng)命令轉(zhuǎn)成短命令,我使用的就是這種方式,相對(duì)來說比較容易理解,且case寫的比較統(tǒng)一。通過shift取出參數(shù),再set --的方式重寫,最后OPTIND=1把指針指回第一個(gè)選項(xiàng)。
文件路徑和文件后綴
按需求需要判斷后綴名來解壓,那么就需要判斷tar.gz之類的問題。同時(shí),如果傳入的文件目錄是隱藏目錄,也會(huì)造成一定的障礙。我們假設(shè)傳入文件路徑為/a/.b/c.tar.gz。
${param#pattern} 從param前面刪除pattern的最小匹配
${param##pattern} 從param前面刪除pattern的最大匹配
${param%pattern} 從param后面刪除pattern的最小匹配
${param%%pattern} 從param后面刪除pattern的最大匹配
如果按照${fileName##*.}來截取,那么只能拿到gz。
如果按照${fileName#*.}來截取,拿到的又是b/c.tar.gz。那怎么辦呢?
好在有dirname可以直接獲取文件路徑,basename拿到文件名,單獨(dú)對(duì)文件名進(jìn)行${fileName#*.}就可以拿到tar.gz了。
去除不必要的打印
執(zhí)行解壓命令時(shí),會(huì)打印解壓步驟,一般來說也需要顯示,那如果我們不想要打印出來呢?有一個(gè)辦法就是在命令之后加上> /dev/null 2>&1
/dev/null :代表空設(shè)備文件
> :代表重定向到哪里,例如:echo "123" > /home/123.txt
1 :表示stdout標(biāo)準(zhǔn)輸出,系統(tǒng)默認(rèn)值是1,所以">/dev/null"等同于"1>/dev/null"
2 :表示stderr標(biāo)準(zhǔn)錯(cuò)誤
& :表示等同于的意思,2>&1,表示2的輸出重定向等同于1
所以含義就是把命令輸出結(jié)果和錯(cuò)誤輸出重定向,使得輸出不在當(dāng)前屏幕顯示,由于null比較特殊,向這個(gè)文件輸入等于進(jìn)入黑洞,因此達(dá)到效果。
數(shù)組與空格
使用ls | grep的方式來過濾結(jié)果獲取文件名數(shù)組的最大問題是,如果文件名包含空格,那么前后會(huì)被分割成兩個(gè)單元,導(dǎo)致處理比較困難。
比較討巧的方法是臨時(shí)用特殊符號(hào)代替空格,在使用時(shí)再替換回來。這種方法不會(huì)改變文件名,也不用寫復(fù)雜的數(shù)組合并,比較符合簡(jiǎn)單的設(shè)計(jì)。
tr " " "?" ${logName//'?'/' '}總結(jié)
通過這次簡(jiǎn)單的腳本實(shí)驗(yàn),對(duì)shell有了新的認(rèn)識(shí),及時(shí)記錄遇到的問題,相信下次會(huì)更有印象。使用腳本,可以讓工作更有效率,相信以后也會(huì)越用越多。
轉(zhuǎn)載于:https://www.cnblogs.com/vanch/p/9682554.html
總結(jié)
- 上一篇: python 的 购物小程序
- 下一篇: 批处理之坑爹的感叹号和变量延迟扩展