java 通过shell命令来操作服务器上的文件,实现复制、编辑内容等。

备注:根据自己的业务可以去修改一下。下面只是实现了我的业务:将服务器上的文件复制到另一个文件下,并且在指定的内容处添加内容。

1.pom文件

      <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
      <dependency>
          <groupId>com.jcraft</groupId>
          <artifactId>jsch</artifactId>
          <version>0.1.55</version>
      </dependency>

      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2 -->
      <dependency>
          <groupId>ch.ethz.ganymed</groupId>
          <artifactId>ganymed-ssh2</artifactId>
          <version>262</version>
      </dependency>

      <dependency>
          <groupId>ch.ethz.ganymed</groupId>
          <artifactId>ganymed-ssh2</artifactId>
          <version>build210</version>
      </dependency>

2.

package com.ed.core.util;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SFTPv3Client;
import ch.ethz.ssh2.SFTPv3DirectoryEntry;
import ch.ethz.ssh2.StreamGobbler;
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * @ProjectName: gitIdeaWork
 * @Package: com.ed.core.util
 * @ClassName: DestHostShell
 * @Author: zhao
 * @Description:
 * @Date: 2019/12/23 18:18
 * @Version: 1.0
 */
public class DestHostShell {
    Logger logger = LoggerFactory.getLogger(DestHostShell.class);

    private static String userName = "***";
    private static String password = "***";
    private static String host = "***.***.*.**";
    private static Integer port = 22;

    /**
     * 文件复制
     * cpCommand : cp /home/upload/hello.txt /home/include/
     * @param cpCommand
     * @return
     * @throws IOException
     * @throws JSchException
     */
    public static void execCommandByShell(String cpCommand)throws IOException,JSchException{

        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession(userName, host, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");//第一次访问服务器不用输入yes
            session.setTimeout(60*60*1000);
            session.connect();

            //2.尝试解决 远程ssh只能执行一句命令的情况
            ChannelShell channelShell = (ChannelShell) session.openChannel("shell");
            InputStream inputStream = channelShell.getInputStream();//从远端到达的数据  都能从这个流读取到
            channelShell.setPty(true);
            channelShell.connect();

            OutputStream outputStream = channelShell.getOutputStream();//写入该流的数据  都将发送到远程端
            //使用PrintWriter 就是为了使用println 这个方法
            //好处就是不需要每次手动给字符加\n
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println(cpCommand);
            printWriter.println("exit");//为了结束本次交互
            printWriter.flush();//把缓冲区的数据强行输出

            /**
             shell管道本身就是交互模式的。要想停止,有两种方式:
             一、人为的发送一个exit命令,告诉程序本次交互结束
             二、使用字节流中的available方法,来获取数据的总大小,然后循环去读。
             为了避免阻塞
             */
            byte[] tmp = new byte[1024];
            while(true){
                while(inputStream.available() > 0){
                    int i = inputStream.read(tmp, 0, 1024);
                    if(i < 0) break;
                    String s = new String(tmp, 0, i);
                    if(s.indexOf("--More--") >= 0){
                        outputStream.write((" ").getBytes());
                        outputStream.flush();
                    }
                    System.out.println(s);
                }
                if(channelShell.isClosed()){
                    System.out.println("退出状态"+channelShell.getExitStatus());
                    break;
                }
                try{Thread.sleep(1000);}catch(Exception e){}
            }
            outputStream.close();
            inputStream.close();
            channelShell.disconnect();
            session.disconnect();
            System.out.println("复制完成");
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件内容读取拼接
     * @param directory:/home/testc/include/
     * @param findContent : 指定内容
     * @param replaceContent    替换内容
     * @return
     */
    public static String fileReadStr(String directory,String findContent,List<String> replaceContent,String fileName,String path){
        //声明连接对象
        Connection conn = null;
        ch.ethz.ssh2.Session ss=null;
        //参数
        List<String> fileNameList=new ArrayList<String>();  //存放文件名
        try {
            //连接远程服务器
            // 连接部署服务器
            conn = new Connection(host);
            conn.connect();
            //使用用户名和密码登录
            boolean b = conn.authenticateWithPassword(userName, password);
            if (!b) {
                throw new IOException("身份验证失败!");
            } else {
                SFTPv3Client sft = new SFTPv3Client(conn);
                Vector<?> v = sft.ls(directory);//日志文件存放的目录
                //遍历该目录下的所有文件
                for (int i = 0; i < v.size(); i++) {
                    SFTPv3DirectoryEntry s = new SFTPv3DirectoryEntry();
                    s = (SFTPv3DirectoryEntry) v.get(i);
                    //文件名
                    String filename = s.filename;
                    if (filename.length() > 0 && filename.equals(fileName)) {
                        //获取符合要求的文件名
                        System.out.println("符合条件的文件名 - >"+filename);
                        fileNameList.add(filename);
                    }
                }

                List<String> contentList = new ArrayList<>();

                //读取文件内容,并复制给UserInfo对象
                for (int j = 0; j<fileNameList.size() ; j++) {
                    ss=conn.openSession();  //打开会话
                    ss.execCommand("cat ".concat(directory+fileNameList.get(j)));  //读取对应目录下的对应文件
                    InputStream    is = new StreamGobbler(ss.getStdout());
                    InputStreamReader gbk = new InputStreamReader(is, "UTF-8");
                    BufferedReader bs = new BufferedReader(gbk);  //防止中文乱码
                    int lineCount = 0;
                    while(true){
                        String line=bs.readLine();
                        if(line==null){
                            break;
                        }else{
                            contentList.add(line);
                            lineCount++;
                            System.out.println( "第" + lineCount + "行,内容为:" + line);
                            //不等于#号,原因是防止这行注释掉
                            if(line.indexOf(findContent) != -1 && line.indexOf("#") == -1){
                                for(int i = 0; i < replaceContent.size(); i++){
                                    contentList.add(replaceContent.get(i));
                                }
                            }
                        }
                    }
                    bs.close();
                }
                ss.close();
                conn.close();

                upLoadToIgenetech(contentList,fileName,path);
            }
        } catch (IOException e) {
            System.err.printf("用户%s密码%s登录服务器%s失败!", userName, password, host);
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 文件内容编辑
     * @param contentList   :内容
     * @param fileName  :文件名称
     * @param dPath : /home/include/
     */
    public static void upLoadToIgenetech(List<String> contentList, String fileName, String dPath){
        JSch jsch = new JSch();
        Session session = null;
        try {
            //用户名、ip地址、端口号
            session = jsch.getSession(userName, host, port);
        } catch (JSchException e) {
            e.printStackTrace();
        }
        // 设置登陆主机的密码
        session.setPassword(password);// 设置密码
        // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
        session.setConfig("StrictHostKeyChecking", "no");
        // 设置登陆超时时间
        try {
            session.connect(300000);
        } catch (JSchException e) {
            e.printStackTrace();
        }
        Channel channel = null;
        try {
            channel = (Channel) session.openChannel("sftp");
            channel.connect(10000000);
            ChannelSftp sftp = (ChannelSftp) channel;
            try {
                sftp.cd(dPath);
            } catch (SftpException e) {
                sftp.mkdir(dPath);
                sftp.cd(dPath);
            }
            OutputStream o = null;
            File file = new File(dPath + "/" + fileName);
            o = sftp.put(file.getName());
            new File(dPath + "/" + fileName);
            for(int i = 0; i < contentList.size(); i++){
                o.write((contentList.get(i) + "\r\n").getBytes("UTF-8"));
            }
            o.close();

            System.out.println("编辑完成!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.disconnect();
            channel.disconnect();
        }
    }
}

3.本地测试好使,部署在服务器上,立马不行,开始报错。各种百度好多坑,终于找到了解决办法
发现是由于JRE缺少包导致,添加包解决:
sunjce_provider.jar
位于本地JRE目录jre/lib/ext/下
将上面那个包复制到你自己项目的下面就ok。

 JSchException: Session.connect: java.security.NoSuchAlgorithmException: DH KeyPairGenerator not avai

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值