shell實例——獲取FTP/SFTP遠程文件

使用Unix/Linux系列操做系統就離不開shellshell本質是和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_downloadsftp_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"
相關文章
相關標籤/搜索