使用Unix/Linux
系列操作系統(tǒng)就離不開shell
,shell
本質(zhì)是和GUI
一樣作為用戶和操作系統(tǒng)之間的接口而存在,它實際上是一個能夠解釋和分析用戶鍵盤輸入飒炎,執(zhí)行輸入的命令因妙,然后返回結(jié)果的解釋程序荐操。由于占用資源少诅妹,而且具有批處理功能历涝,實際開發(fā)和維護(hù)當(dāng)中掌握必要的shell
技能,勢必會大大提升工作效率。
以下記錄了一個shell
腳本實例荧库,是為解決實際生產(chǎn)問題而編寫。我使用的是AIX
下語法較嚴(yán)格的kshell
赵刑。
需求描述
深證通會將基金公司的確認(rèn)數(shù)據(jù)文件(開戶分衫、認(rèn)申購定投、贖回分紅等等)發(fā)送給對接過的小站般此,最終體現(xiàn)就是不同的小站各推到接收方一個獨(dú)立的文件夾(文件夾以小站號命名)蚪战。我作為接收方有一臺存儲服務(wù)器用于接收小站文件,此時另外一臺應(yīng)用服務(wù)器需要從存儲服務(wù)器獲取確認(rèn)數(shù)據(jù)文件铐懊。數(shù)據(jù)文件按類別不同分別有03邀桑、04、06等結(jié)尾的科乎,每天會有更新壁畸。要求是獲取每天的04、06新文件茅茂,每天的文件分別放在當(dāng)天日期命名的文件夾下捏萍。
# 遠(yuǎn)端存儲服務(wù)器目錄結(jié)構(gòu)
|——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
| └──....
└──...
環(huán)境介紹
操作系統(tǒng):AIX
$ oslevel
7.1.0.0
$ echo $SHELL
/usr/bin/ksh
$ expect -v
expect version 5.42.1
代碼實現(xiàn)
1、定義變量
首先定義變量給定參數(shù)空闲,包括FTP/SFTP
的用戶信息和路徑令杈,小站文件夾名稱,這里我用數(shù)組來存放小站文件夾名稱碴倾,等下就可以遍歷數(shù)組獲取文件逗噩,后續(xù)維護(hù)也比較方便〉疲可以直接在腳本里寫好參數(shù)异雁,也可以用傳參的方式。
# 接收參數(shù)
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"
2矫户、處理文件夾
先判斷本地是否存在當(dāng)日日期文件夾片迅,不存在則創(chuàng)建文件夾,并賦予權(quán)限755
皆辽,然后轉(zhuǎn)到該目錄下柑蛇。
# [函數(shù)]處理日期文件夾
createForlder()
{
cd $1
if [[ ! -d ${SYSDATE} ]]; then
mkdir ${SYSDATE}
chmod 755 ${SYSDATE}
fi
cd ${SYSDATE}
}
3、非交互式遠(yuǎn)程登錄
要想通過shell
腳本登錄FTP
驱闷,就需要使用非交互式的方式讓腳本自動填充指令信息耻台,FTP
使用-n
參數(shù)打開非交互式操作
# FTP非交互式操作
ftp_download()
{
ftp -n $1 <<!
user $2 $3
prom
bin
cd $4
mget *$sysdate*04.*
mget *$sysdate*06.*
bye
!
}
如果使用的是SFTP
協(xié)議,那么此協(xié)議是沒有提供非交互式參數(shù)可以使用的空另,此時有兩種方案可以解決盆耽,一種就是讓遠(yuǎn)程服務(wù)器端保存本機(jī)的MAC密鑰
,從而自動驗證免密登錄。當(dāng)然對于很多對安全性要求較高的情況來說是不允許這種方式的摄杂。另外一種就是使用自動化交互工具expect
坝咐,具體實現(xiàn)如下:
# 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
}
4、遍歷小站獲取文件
循環(huán)遍歷數(shù)組STATION_ARR[]
獲得小站文件夾名稱析恢,并拼接好遠(yuǎn)程路徑remoteDir
墨坚,然后調(diào)用函數(shù)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
至此映挂,需求功能已全部實現(xiàn)泽篮。完整腳本代碼如下:
#!/usr/bin/ksh
############################################################
## 功能:從存儲服務(wù)器獲取確認(rèn)文件
## By xiaosong 2017-12-31
############################################################
#------------------------參數(shù)說明----------------------------
#--接收
# localPath -本地文件路徑
# remotePath -遠(yuǎn)程文件路徑
# serverIP -遠(yuǎn)程服務(wù)器IP
# sftpUser -sftp用戶名
# sftpPass -sftp密碼
#--變量
# SYSDATE -系統(tǒng)日期
# STATION_ARR[] -小站文件夾數(shù)組,新增小站增加此數(shù)組即可
#-----------------------------------------------------------
# 接收參數(shù)
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"
# [函數(shù)]處理日期文件夾
createForlder()
{
cd $1
if [[ ! -d ${SYSDATE} ]]; then
mkdir ${SYSDATE}
chmod 755 ${SYSDATE}
fi
cd ${SYSDATE}
}
# [函數(shù)]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
完善腳本
1柑船、參數(shù)校驗
腳本功能函數(shù)執(zhí)行前帽撑,可以校驗是否傳遞了完整的參數(shù)。若參數(shù)個數(shù)不對鞍时,則直接退出腳本終止執(zhí)行亏拉。
if [[ $# != 5 ]]; then
exit
fi
2、日志
為腳本增加日志函數(shù)寸癌,記錄腳本運(yùn)行情況专筷,作為歷史記錄歸檔,也方便回查定位問題蒸苇。
SYSTIME=`date '+%Y-%m-%d %H:%M:%S'`
# [函數(shù)]腳本運(yùn)行日志
wLog(){
echo "${SYSTIME} $1" >> ${LOGPATH}/DownloadFile.log
}
3磷蛹、返回值
如果不是配置crontab
定時任務(wù)執(zhí)行腳本,而是通過其他方式調(diào)用腳本執(zhí)行溪烤,那么可能還需要為腳本設(shè)置返回值味咳。
#-----------------------------------------------------------
#--返回值RETURNCODE
# 0 -成功
# 1 -參數(shù)傳遞異常
# 2 -處理文件夾異常
# 3 -獲取文件異常
#-----------------------------------------------------------
# [函數(shù)]腳本執(zhí)行返回值
retrunCode()
{
if [ ${result} -eq "1" ]; then
RETURNCODE=$1
echo ${RETURNCODE}
fi
}
然后在關(guān)鍵步驟位置調(diào)用返回值處理函數(shù)。
# 校驗參數(shù)個數(shù)
if [[ $# != 5 ]]; then
exit
fi
result=$?
retrunCode "1"
# 處理文件夾
createForlder ${localPath}
result=$?
retrunCode "2"
# 循環(huán)獲取文件
for station in ${STATION_ARR[@]}; do
remoteDir=${remotePath}${station}
sftp_download ${sftpUser} ${serverIP} ${sftpPass} ${remoteDir}
done
result=$?
retrunCode "3"