使用Unix/Linux
系列操做系統就離不開shell
,shell
本質是和GUI
同樣做爲用戶和操做系統之間的接口而存在,它其實是一個可以解釋和分析用戶鍵盤輸入,執行輸入的命令,而後返回結果的解釋程序。因爲佔用資源少,並且具備批處理功能,實際開發和維護當中掌握必要的shell
技能,勢必會大大提高工做效率。shell
如下記錄了一個shell
腳本實例,是爲解決實際生產問題而編寫。我使用的是AIX
下語法較嚴格的kshell
。數組
深證通會將基金公司的確認數據文件(開戶、認申購定投、贖回分成等等)發送給對接過的小站,最終體現就是不一樣的小站各推到接收方一個獨立的文件夾(文件夾以小站號命名)。我做爲接收方有一臺存儲服務器用於接收小站文件,此時另一臺應用服務器須要從存儲服務器獲取確認數據文件。數據文件按類別不一樣分別有0三、0四、06等結尾的,天天會有更新。要求是獲取天天的0四、06新文件,天天的文件分別放在當天日期命名的文件夾下。安全
# 遠端存儲服務器目錄結構 |——download |——k0001 | |——YYYYMMdd_xx_xxx_xxxxxxxx_03.TXT | |——YYYYMMdd_xx_xxx_xxxxxxxx_04.TXT | |——YYYYMMdd_xx_xxx_xxxxxxxx_06.TXT | └──... |——k0253 | |——OFD_xx_xxx_YYYYMMdd_03.TXT | |——OFD_xx_xxx_YYYYMMdd_04.TXT | |——OFD_xx_xxx_YYYYMMdd_06.TXT | └──.... |──zdfile | |——YYYYMMdd_xx_xxx_xxxxxxxx_03.TXT | |——YYYYMMdd_xx_xxx_xxxxxxxx_04.TXT | |——YYYYMMdd_xx_xxx_xxxxxxxx_06.TXT | |——OFD_xx_xxx_YYYYMMdd_03.TXT | |——OFD_xx_xxx_YYYYMMdd_04.TXT | |——OFD_xx_xxx_YYYYMMdd_06.TXT | └──.... └──...
AIX
服務器
$ oslevel 7.1.0.0 $ echo $SHELL /usr/bin/ksh $ expect -v expect version 5.42.1
首先定義變量給定參數,包括FTP/SFTP
的用戶信息和路徑,小站文件夾名稱,這裏我用數組來存放小站文件夾名稱,等下就能夠遍歷數組獲取文件,後續維護也比較方便。能夠直接在腳本里寫好參數,也能夠用傳參的方式。函數
# 接收參數 localPath=$1 remotePath=$2 serverIP=$3 sftpUser=$4 sftpPass=$5 # 定義變量 SYSDATE=`date +%Y%m%d` STATION_ARR[0]="k0001" STATION_ARR[1]="k0253" STATION_ARR[2]="zdfile"
先判斷本地是否存在當日日期文件夾,不存在則建立文件夾,並賦予權限755
,而後轉到該目錄下。工具
# [函數]處理日期文件夾 createForlder() { cd $1 if [[ ! -d ${SYSDATE} ]]; then mkdir ${SYSDATE} chmod 755 ${SYSDATE} fi cd ${SYSDATE} }
要想經過shell
腳本登陸FTP
,就須要使用非交互式的方式讓腳本自動填充指令信息,FTP
使用-n
參數打開非交互式操做spa
# FTP非交互式操做 ftp_download() { ftp -n $1 <<! user $2 $3 prom bin cd $4 mget *$sysdate*04.* mget *$sysdate*06.* bye ! }
若是使用的是SFTP
協議,那麼此協議是沒有提供非交互式參數可使用的,此時有兩種方案能夠解決,一種就是讓遠程服務器端保存本機的MAC密鑰
,從而自動驗證免密登陸。固然對於不少對安全性要求較高的狀況來講是不容許這種方式的。另一種就是使用自動化交互工具expect
,具體實現以下:操作系統
# SFTP非交互式操做 sftp_download() { expect <<- EOF set timeout 5 spawn sftp $1@$2 expect { "(yes/no)?" {send "yes\r"; expect_continue} "password:" {send "$3\r"} } expect "sftp>" send "cd $4\r" set timeout -1 expect "sftp>" send "mget *$sysdate*04.*\r" expect "sftp>" send "mget *$sysdate*06.*\r" expect "sftp>" send "bye\r" EOF }
循環遍歷數組STATION_ARR[]
得到小站文件夾名稱,並拼接好遠程路徑remoteDir
,而後調用函數ftp_download
或sftp_download
獲取文件。日誌
for station in ${STATION_ARR[@]}; do remoteDir=${remotePath}${station} ftp_download ${serverIP} ${sftpUser} ${sftpPass} ${remoteDir} # sftp_download ${sftpUser} ${serverIP} ${sftpPass} ${remoteDir} done
至此,需求功能已所有實現。完整腳本代碼以下:code
#!/usr/bin/ksh ############################################################ ## 功能:從存儲服務器獲取確認文件 ## By xiaosong 2017-12-31 ############################################################ #------------------------參數說明---------------------------- #--接收 # localPath -本地文件路徑 # remotePath -遠程文件路徑 # serverIP -遠程服務器IP # sftpUser -sftp用戶名 # sftpPass -sftp密碼 #--變量 # SYSDATE -系統日期 # STATION_ARR[] -小站文件夾數組,新增小站增長此數組便可 #----------------------------------------------------------- # 接收參數 localPath=$1 remotePath=$2 serverIP=$3 sftpUser=$4 sftpPass=$5 # 定義變量 SYSDATE=`date +%Y%m%d` STATION_ARR[0]="k0001" STATION_ARR[1]="k0253" STATION_ARR[2]="zdfile" # [函數]處理日期文件夾 createForlder() { cd $1 if [[ ! -d ${SYSDATE} ]]; then mkdir ${SYSDATE} chmod 755 ${SYSDATE} fi cd ${SYSDATE} } # [函數]SFTP非交互式操做 sftp_download() { expect <<- EOF set timeout 5 spawn sftp $1@$2 expect { "(yes/no)?" {send "yes\r"; expect_continue} "password:" {send "$3\r"} } expect "sftp>" send "cd $4\r" set timeout -1 expect "sftp>" send "mget *$sysdate*04.*\r" expect "sftp>" send "mget *$sysdate*06.*\r" expect "sftp>" send "bye\r" EOF } # 獲取中登文件 createForlder ${localPath} for station in ${STATION_ARR[@]}; do remoteDir=${remotePath}${station} sftp_download ${sftpUser} ${serverIP} ${sftpPass} ${remoteDir} done
腳本功能函數執行前,能夠校驗是否傳遞了完整的參數。若參數個數不對,則直接退出腳本終止執行。
if [[ $# != 5 ]]; then exit fi
爲腳本增長日誌函數,記錄腳本運行狀況,做爲歷史記錄歸檔,也方便回查定位問題。
SYSTIME=`date '+%Y-%m-%d %H:%M:%S'` # [函數]腳本運行日誌 wLog(){ echo "${SYSTIME} $1" >> ${LOGPATH}/DownloadFile.log }
若是不是配置crontab
定時任務執行腳本,而是經過其餘方式調用腳本執行,那麼可能還須要爲腳本設置返回值。
#----------------------------------------------------------- #--返回值RETURNCODE # 0 -成功 # 1 -參數傳遞異常 # 2 -處理文件夾異常 # 3 -獲取文件異常 #----------------------------------------------------------- # [函數]腳本執行返回值 retrunCode() { if [ ${result} -eq "1" ]; then RETURNCODE=$1 echo ${RETURNCODE} fi }
而後在關鍵步驟位置調用返回值處理函數。
# 校驗參數個數 if [[ $# != 5 ]]; then exit fi result=$? retrunCode "1" # 處理文件夾 createForlder ${localPath} result=$? retrunCode "2" # 循環獲取文件 for station in ${STATION_ARR[@]}; do remoteDir=${remotePath}${station} sftp_download ${sftpUser} ${serverIP} ${sftpPass} ${remoteDir} done result=$? retrunCode "3"