shell脚本实现文件的自动上传以及下载 scp sftp lftp 还有expect命令 2018年6月1日

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013408059/article/details/80542360

最近需求要求定期从一个[定期更新的文件] 中解析员工信息 ,插入到数据库中. 

    按理来说很简单,  无非就是io流读文件,然后crud balalalala.....

 其实不是的, 我我写的这个接口 ,要实现从远程服务器上获取文件然后入库操作 . . . 问题来了,  我怎么去读文件.

这样就用到了linux的命令了 ,大致来说 , 从远程服务器上获取文件有好几种方式 , scp快速获取 sftp建立ssh连接 ,lftp连接  好像还有个rsync什么的,这个没记住 ....

 大致命令为


下载: 如果(-p端口号不好使 就替换成 -oPort=端口号)

scp -p端口号   远程服务器用户@远程服务器ip:文件路径   本地存放路径   

    

例子: scp -p22 [email protected]:/usr/wang.txt  /usr/wang.txt     这个好像不能scp的时候改名字

sftp -p端口号  远程服务器用户@远程服务器ip 建立连接之后:

get  要下载的文件路径+文件名    本地存储路径

put    本地存储路径   要上传的文件路径+文件名 

quit 或者exit  可以退出ssh连接

例子 懒得写了, 直接截屏吧



lftp 这个我是和sftp 同时用的 有一个好处可以免登陆的:

现在上图:.......

     码的公司服务器好像断了 (掀桌!), 算了不截屏了 , 老老实实码字吧.. . . . . . .


这个是点击之后 , 就会进入  

这个时候  cd  远程服务器目录    这个命令就是进入远程服务器的目录

               lcd  本地存放目录      这个额命令就是进入本地需要存放的目录

             get   需要下载文件名     

              put   需要上传的文件名

quit或者   exit 退出       


其实我要说的命令直接百度就能搜到 , 接下来就是实现自动上传或下载了 ,大致有三种 , 我实现了有两种 , 看这个大神的

点击打开大神总结

第一种:使用lftp+sftp 命令

第二种:使用expect 命令

第三种:配置免密 看这个写得很清楚点击打开链接  大致就是使用- keygen 生成密钥,将公钥交给远程服务器以配置免登录

注意:你用那个用户获取的密钥,你就要cd到那个用户的cd /用户名/.ssh/公钥文件   下, 我就是用admin用户获取到 ,但是发现进不去/root/.ssh/  目录下 , 大概我是个接触脚本两天的小白把 ,maybe。。。。


第一种:

#!/usr/bin/bash    // 这个头部很重要
trandt=`date +%Y%m%d`
lastdt=`date -d "$trandt -2 day " +%Y%m%d`
var1=dim_user_
var2=.txt
 #文件名
filename=${var1}${lastdt}${var2}   /需求上说的是文件名跟日期变动的,所以我的文件名这么写 ,   可以写死的!
USER=wodemingzi
 #密码
PASSWORD=wodemima
#下载文件目录
#LOCAL=/usr/local/src/            文件admin没有读写权限
LOCAL=/home/admin/   // 尽量放在这个目录下吧  有的应用没有其他文件夹的读写权限
#FTP目录(待下载文件目录)
 REMOTE=/jd_tfm_file/  
 #银联IP
IP=10.10.10.168
 #端口
PORT=2374
lftp -u ${USER},${PASSWORD} sftp://${IP}:${PORT}<<EOF
 cd ${REMOTE}
lcd ${LOCAL}
 #需要下载的文件
get ${filename}
EOF

这个脚本其实不算难 , 但是实现的时候非常的艰难 , 首先是脚本不能执行的问题 , 需要注意的地方我加粗了 这个文件的名字为lftp.sh

是个shell脚本文件, 需要 是sh  lftp.sh 来运行的 . 

其次就是文件不能执行的问题:

文件权限需要用   chmod 777 脚本文件.sh   获取权限      

+++++++++++++++++++++++++++今天先写到这, 明天再写吧++++++++++++++++++++++++++++++++

继续写:

文件获取权限之后 ,使用sh  lftp.sh就可以执行了


但是有一个问题, 看贴图吧


我使用cat命令,把脚本粘贴到命令行执行, 

wht?!!!没有报告任何错误 , 直接就把远程服务器文件get到了我本地指定目录里面。


错误.jpg

假装有图,  

发现执行到, 这里 , 就不执行了 , 始终搞不懂到底是为啥 , 百度了各大资料, 有人说 这是lftp命令没装好, 有人说这是没有指定目录, 还有人用./wang.sh 的方式 ,还有人说是用户权限的问题 , 我把代码粘出来就能执行你告诉我是权限的问题??!!!

总之全他么的不好使 ,最后本人媳妇(大神)告诉我 ,你这个文件的声明不对吧,,,shell脚本声明头应该是这样的

 
 
#!/usr/bin/bash

看到我之前发的截图吗 , 头部明显不太对 , 好吧, 然后我就改了  ,然后继续用

 sh  wang.sh  ;

发现还是不好使 ; 报的错不粘出来了 , 这次是真的没办法了, 我就放弃了一段时间 ,然后干别的去了......

=======n小时后, 我又开始验证这段脚本 了, 不好使 , 不知道怎么回事,我进入了这个大神的博客 , 我其实不想验证的,因为我一开始就害怕脚本是dos格式的 ,我就全删了,然后在linux中手打了一遍的......

反正闲的蛋疼, 我就用

vi wang.sh     

按Esc , 输入 冒号 ff见下面 

 : set ff                      ===>>> 得到的他么的竟然是   'dos' , !!!!!!!!!!!这回真的是伤了

先弄好了吧 , 输入 冒号 set ff=unix  

: set ff=unix       ,==>>>>再输入 :set ff  发现就变成   unix  了 . 

好这次我继续敲:  

 sh  wang.sh  ;    ^_^,终于成功了!!!!

第一种方式完成!!!!!

  总结: 脚本

        第一要先验证脚本格式是什么类型的,是dos 还是unix 的 ,这个很重要 链接在这里

        https://blog.csdn.net/chengxuyuanyonghu/article/details/47340123

        第二,一定要注意头部一定要正确, 确保你的命令在linux中已经安装了

        第三,确保你的脚本文件时一个可执行的文件 , 不可执行,使用 chmod 777 文件名 获取权限

      第四:这个我最后遇到了, 不过懒得再复述了. , 在你的脚本中设置 本地存放路径(lcd 路径) 的时候 ,一定要确保你的当前用户(不管是root还是 admin还是其他) 是拥有这个目录的读写权限的,这个存放目录建议就放在/home/用户名/  这个目录下最靠谱.

第五: 没了.(对了,就算做到了这些, 也要确保远程服务器和本地服务器的连通性 ,先使用单行命令,是不是能连通 ,然后再去测脚本)


============================o(╥﹏╥)o=============================

第二种方式: 使用expect 命令的方式 , 

很不幸, 我的这个不好使 , 一直报告找不到

spawn  not found 

     我确实安装了 expect 命令

贴一下代码吧


没办法 , 我试了上述那几个总结, 依旧不好使

希望你们能发现是什么问题:

首先使用命令安装了expect 我使用 exp expect.exp 也跑不动这个脚本.

总之这个就弃用了.

============================o(╥﹏╥)o=============================

第三种方式: 配公钥

        也是最方便的最快捷的方式 配置公钥的方式,配置完了可以直接使用scp 命令  ,sftp 命令 ,lftp 命令 一行就把文件neng过来!

上面写过链接了, 再发一遍点击打开链接

写的很清楚了, 使用

ssh-keygen     ===>>然后一路回车 ,

会生成一个小图片 ,圈圈点点之类的 , 同时会在你的 /home/用户名/.ssh/  家目录下生成  公钥和私钥,

私钥文件(id_rsa)和公钥文件(id_rsa.pub)   公钥文件 使用 cat  id_rsa.pub   命令

打开 , 将里面的内容复制到===>>>>远程服务器下同级目录下的authorized_keys(没有这个文件就创建一个就行) 中,多行要回车 隔开.

直接拿大神截图过来用了,参考下......-_-||(公司又断网了)


直接用scp  -p22  [email protected]:/export/123.txt  /home/root/123.txt    可以拉取到我本地

     用  sftp -oPort(同一公司内服务器用-p就行)=22  [email protected] , 可以直接连接上 不需要输入密码了;

 然后  cd  /export/           ===>>>到远程目录下

        cd /home/root/     ===>>>到本地目录下

         get   文件名            ===>>>妥妥的复制过来了(put也一样)

lftp 上面写过了.


把java代码也粘一下.(目前还不想使用github,因为比较菜 ,不想过多把精力放在这上面 ,文章也懒得排版,想到哪就写到哪了.....有问题加我球球号952288306 交流)

执行脚本的java代码:

package com.jd.ecc.tianfu.tools;

import com.jd.ecc.tianfu.utils.FileUtils;

import java.io.*;

/**
 * 
 * @author wangwenbin1
 * 执行脚本的工具类
 */
public class JavaLinuxManager {
	
	public String Linuxscp(String img,String encode){
		String msg = null;
		try {
			 Process ps = Runtime.getRuntime().exec(img);
			 ps.waitFor();
			  msg = loadStream(ps.getErrorStream(),encode);
			 System.err.print(msg);
			 ps.destroy();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return msg;
	}
	
	static String loadStream(InputStream in,String encode) throws IOException {
        //把所有的数据读取到这个字节当中
        byte[] b = new byte[1024];
        //声明一个int存储每次读取到的数据
        int i = 0;
        //定义一个记录索引的变量
        int index = 0;
        //循环读取每个数据
        while((i=in.read())!=-1) {//把读取的数据放到i中
            b[index] = (byte) i;
            index++;
        }
        return new String(b,encode==null?"utf-8":"gbk");
    }
	
//	 public static void main(String[] args) throws Exception {
//       File file =   new File("d:a.txt");
//         FileInputStream fileIn = new FileInputStream(file);
//         String s = loadStream(fileIn, FileUtils.encoded(file));
//         System.out.println(s);
//     }
}

controller很简单, 就是 不少注解是swagger的 可以忽略 ,主要看加粗的部分

@ApiOperation(value = "執行java脚本")
@RequestMapping(value = "/runtime/img", produces = "application/json;charset=utf-8")
public RespData<Map<String, Object>> img(
        @ApiParam(value = "平台ID", required = true) @RequestParam("platformId") Long platformId,
        @ApiParam(value = "脚本或者文件路径(chmod 777 ./WEB-INF/shs/sftp.sh)", required = true) @RequestParam("img") String img, HttpServletRequest request,
        @ApiParam(value = "验证码", required=true) @RequestParam(value = "authcode",required = true)String authcode) {
    try {
        //  chmod 777 ./WEB-INF/shs/sftp.sh
        if ("XXX一个验证码省得别人恶意拼接XXXXX".equals(authcode)){
        JavaLinuxManager unix = new JavaLinuxManager();
        String linuxscp = unix.Linuxscp(img, null);
        Map<String,Object> map =  new HashMap<>();
        map.put("msg",linuxscp);
        return RespData.success(map);
        }else {
            return RespData.error("0000","验证码失败!!!");
        }
    } catch (Exception e) {
        LOG.error("执行异常!", e);
        e.printStackTrace();
    }
    return RespData.error("0000", "执行异常");
}


附一个文件工具类:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;




/**
 * 读取文本工具类
 * @author wangwenbin1
 *
 */
public class FileUtils {

   private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(FileUtils.class);
   
   /**
    * 判断文件是否存在 不存在创建空文件
    * @param file
    * @return
    * @throws IOException
    */
   public static boolean isExistFile(File file) throws IOException {
        // 判断是否存在
        if (file.exists()) {
            // 判读是否是一个文件
            return file.isFile();
        } else if (file.length() == 0) {
            LOG.info("文件内容为空");
        } else {
            LOG.info("文件不存在!");
        }
        return false;
    }
   
   /**
    * 判断文件的编码方式
    * @param file
    * @return
    * @throws IOException
    */
   public static String encoded(File file) throws IOException{
      InputStream in = new FileInputStream(file);
      byte[] b = new byte[3];
      in.read(b);
      in.close();
      if (b[0]==-17&&b[1]==-69&&b[2]==-65) {
         // 一般来说,utf-8 的前三个字符为上述三个
         LOG.info("文件utf-8编码!");
         return "utf-8";
      }else{
         LOG.info("文件gbk编码!");
         return "gbk";
      }
   }
   /**
    * 读取txt文件 返回Sting
    * @param path
    * @return
    * @throws IOException
    */
   public static String readTXTFile(String path) throws IOException {
        File file = new File(path);
        boolean existFile = isExistFile(file);
        if (existFile) {
            LOG.info("文件存在且内容非空!");
            String charset = encoded(file);
            InputStreamReader reader = new InputStreamReader(new FileInputStream(file), charset);
            BufferedReader bf = new BufferedReader(reader);
            StringBuffer sb = new StringBuffer();
            String text = "";
            while ((text = bf.readLine()) != null) {

                sb.append(text);
                sb.append(";");
                //sb.append("\r\n");
            }
            String sbNew = sb.substring(0, sb.length() - 1);
            reader.close();
            bf.close();
            return sbNew;
        }
        return "";
    }

}


猜你喜欢

转载自blog.csdn.net/u013408059/article/details/80542360