shell实例——获取FTP/SFTP远程文件

使用Unix/Linux系列操作系统就离不开shellshell本质是和GUI一样作为用户和操作系统之间的接口而存在,它实际上是一个能够解释和分析用户键盘输入,执行输入的命令,然后返回结果的解释程序。由于占用资源少,而且具有批处理功能,实际开发和维护当中掌握必要的shell技能,势必会大大提升工作效率。

以下记录了一个shell脚本实例,是为解决实际生产问题而编写。我使用的是AIX下语法较严格的kshell

需求描述

深证通会将基金公司的确认数据文件(开户、认申购定投、赎回分红等等)发送给对接过的小站,最终体现就是不同的小站各推到接收方一个独立的文件夹(文件夹以小站号命名)。我作为接收方有一台存储服务器用于接收小站文件,此时另外一台应用服务器需要从存储服务器获取确认数据文件。数据文件按类别不同分别有03、04、06等结尾的,每天会有更新。要求是获取每天的04、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

代码实现

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"

2、处理文件夹

先判断本地是否存在当日日期文件夹,不存在则创建文件夹,并赋予权限755,然后转到该目录下。

# [函数]处理日期文件夹
createForlder()
{
    cd $1
    if [[ ! -d ${SYSDATE} ]]; then
        mkdir ${SYSDATE}
        chmod 755 ${SYSDATE}
    fi
    cd ${SYSDATE}
}

3、非交互式远程登录

要想通过shell脚本登录FTP,就需要使用非交互式的方式让脚本自动填充指令信息,FTP使用-n参数打开非交互式操作

# 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
}

4、遍历小站获取文件

循环遍历数组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

至此,需求功能已全部实现。完整脚本代码如下:

#!/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

完善脚本

1、参数校验

脚本功能函数执行前,可以校验是否传递了完整的参数。若参数个数不对,则直接退出脚本终止执行。

if [[ $# != 5 ]]; then
    exit
fi

2、日志

为脚本增加日志函数,记录脚本运行情况,作为历史记录归档,也方便回查定位问题。

SYSTIME=`date '+%Y-%m-%d %H:%M:%S'`

# [函数]脚本运行日志
wLog(){
    echo "${SYSTIME}  $1" >> ${LOGPATH}/DownloadFile.log
}

3、返回值

如果不是配置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"

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2280端口映射到公网,发现经常被暴力破解,自己写了个临时封禁ip功能的脚本,实现5分钟内同一个ip登录密码错误10次就封禁这个ip5分钟,并且进行邮件通知使用步骤openwrt为19.07.03版本,其他版本没有测试过安装bashmsmtpopkg
#!/bin/bashcommand1&command2&wait从Shell脚本并行运行多个程序–杨河老李(kviccn.github.io)
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/phpls-ls 2.编辑修改.bash_profile文件(没有.bash_profile文件的情况下回自动创建)sudovim~/.bash_profile在文件的最后输入以下信息,然后保存退出exportPATH="/Applications/MAMP/bin/php/php7.2.20/b
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如zh_CN之类的语言包,进行中文语言包装:apt-getinstalllanguage-pack-zh-hans3、安装好后我们可以进行临时修改:然后添加中文支持: locale-genzh_CN.UTF-8临时修改> export LC_ALL='zh_CN.utf8'> locale永久
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexadecimalbash2#[0~1]0[0~7]0x[0~f]or0X[0~f]perl0b[0~1]0[0~7]0x[0~f]tcl0b[0~1]0o[0~7]0x[0~f]bashdifferentbaserepresntationreference2.StringlengthLanguageStr
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全命令补全方法:yum-yinstallbash-completionsource/usr/share/bash-completion/bash_completionsource<(kubectlcompletionbash)echo"source<(kubectlcompletionbash)">>~/.bashrc 
参考这里启动jar包shell脚本修改过来的#!/bin/bash#默认应用名称defaultAppName='./gadmin'appName=''if[[$1&&$1!=0]]thenappName=$1elseappName=$defaultAppNamefiecho">>>>>>本次重启的应用:$appName<
#一个数字的行#!/bin/bashwhilereadlinedon=`echo$line|sed's/[^0-9]//g'|wc-L`if[$n-eq1]thenecho$linefidone<1.txt#日志切割归档#!/bin/bashcd/data/logslog=1.logmv_log(){[-f$1]&&mv$1$2
#文件增加内容#!/bin/bashn=0cat1.txt|whilereadlinedon=[$n+1]if[$n-eq5]thenecho$lineecho-e"#Thisisatestfile.\n#Testinsertlineintothisfile."elseecho$linefidone#备份/etc目录#
# su - oraclesu: /usr/bin/ksh: No such file or directory根据报错信息:显示无法找到文件 /usr/bin/ksh果然没有该文件,但是发现存在文件/bin/ksh,于是创建了一个软连接,可以规避问题,可以成功切换到用户下,但无法执行系统自带命令。$. .bash_profile-ksh: .: .b
history显示历史指令记录内容,下达历史纪录中的指令主要的使用方法如果你想禁用history,可以将HISTSIZE设置为0:#exportHISTSIZE=0使用HISTIGNORE忽略历史中的特定命令下面的例子,将忽略pwd、ls、ls-ltr等命令:#exportHISTIGNORE=”pwd:ls:ls-ltr:”使用HIS
一.命令历史  1.history环境变量:    HISTSIZE:输出的命令历史条数,如history的记录数    HISTFILESIZE:~/.bash_history保存的命令历史记录数    HISTFILLE:历史记录的文件路径    HISTCONTROL:     ignorespace:忽略以空格开头的命令
之前在网上看到很多师傅们总结的linux反弹shell的一些方法,为了更熟练的去运用这些技术,于是自己花精力查了很多资料去理解这些命令的含义,将研究的成果记录在这里,所谓的反弹shell,指的是我们在自己的机器上开启监听,然后在被攻击者的机器上发送连接请求去连接我们的机器,将被攻击者的she
BashOne-LinersExplained,PartI:Workingwithfileshttps://catonmat.net/bash-one-liners-explained-part-oneBashOne-LinersExplained,PartII:Workingwithstringshttps://catonmat.net/bash-one-liners-explained-part-twoBashOne-LinersExplained,PartII
Shell中变量的作用域:在当前Shell会话中使用,全局变量。在函数内部使用,局部变量。可以在其他Shell会话中使用,环境变量。局部变量:默认情况下函数内的变量也是全局变量#!/bin/bashfunctionfunc(){a=99}funcecho$a输出>>99为了让全局变量变成局部变量
1、多命令顺序执行;  命令1;命令2  多个命令顺序执行,命令之间没有任何逻辑联系&&  命令1&&命令2  逻辑与,当命令1正确执行,才会执行命令2||  命令1||命令2  逻辑或,当命令1执行不正确,才会执行命令2例如:ls;date;cd/home/lsx;pwd;who ddif=输入文件of=输
原博文使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗?首先,这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang"。Linux执行文件时发现这个格式,会把!后的内容提取出来拼接在脚本文件或路径之前,当作实际执行的命令。 Shebang这个符号通常在Unix系统的脚本
1、历史命令history[选项][历史命令保存文件]选项:-c:  清空历史命令-w:  把缓存中的历史命令写入历史命令保存文件 ~/.bash_historyvim/etc/profile中的Histsize可改存储历史命令数量历史命令的调用使用上、下箭头调用以前的历史命令使用“!n”重复执行第n条历史
目录1.Shell脚本规范2.Shell脚本执行3.Shell脚本变量3.1环境变量3.1.1自定义环境变量3.1.2显示与取消环境变量3.1.3环境变量初始化与对应文件的生效顺序3.2普通变量3.2.1定义本地变量3.2.2shell调用变量3.2.3grep调用变量3.2.4awk调用变量3.3
   http://www.voidcn.com/blog/wszzdanm/article/p-6145895.html命令功能:显示登录用户的信息命令格式:常用选项:举例:w显示已经登录的用户及正在进行的操作[root@localhost~]#w 11:22:01up4days,21:22, 3users, loadaverage:0.00,0.00,0.00USER