使用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"