Ganymed-ssh2实现scp上传和下载文件,以及执行shell命令

使用Ganymed-ssh2执行远程机器上的Shell脚本,还可以使用SCP来上传和下载文件

严禁转载!!!

pom依赖

        <dependency>
            <groupId>com.airlenet.yang</groupId>
            <artifactId>ganymed-ssh2</artifactId>
            <version>1.2.0</version>
        </dependency>

工具服务

yml配置

scp:
  ip: 192.168.1.22
  port: 22
  userName: root
  password: 123456

工具类


import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Nonnull;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Objects;

/**
 * @descriptions: shell命令和scp文件传输
 * @author: xucl
 */
@Slf4j
@Component
public class ScpHelper {

    @Value("${scp.ip}")
    private String scpIp;

    @Value("${scp.port:22}")
    private Integer scpPort;

    @Value("${scp.userName:root}")
    private String userName;

    @Value("${scp.password}")
    private String password;
    
    private Connection connection;

    /**
     * 初始化
     */
    public synchronized void initConnection(){
        if (Objects.isNull(connection)){
            try {
                connection = new Connection(scpIp, scpPort);
                 connection.connect(null,3000,5000);
            } catch (Exception e) {
                log.error("SCP-初始化SCP连接失败,请配置后再使用该工具!");
                throw new RuntimeException("SCP-初始化SCP连接失败,请配置后再使用该工具!",e);
            }
            boolean b = authenticate(userName, password);
            if (!b){
                try {
                    throw new RuntimeException("SCP-认证失败,无法执行相关命令!");
                } finally {
                    connection.close();
                }
            }
        }
    }

    /**
     * ssh用户登录验证,使用用户名和密码来认证
     *
     * @param userName
     * @param password
     * @return
     */
    public boolean authenticate(String userName, String password) {
        try {
            return connection.authenticateWithPassword(userName, password);
        } catch (IOException e) {
            log.error("SCP-认证异常",e);
        }
        return false;
    }


    private void before(){
        initConnection();
    }

    /**
     * 执行简单的Shell命令
     * @param cmd
     */
    public void execSimpleCmd(String cmd) {
        before();
        Session session = null;
        try {
            session = connection.openSession();
            session.execCommand(cmd);
        } catch (Exception e) {
            log.error("SCP-执行shell命令失败",e);
        } finally {
            if (Objects.nonNull(session)){
                session.close();
            }

        }
    }

    /**
     * 执行复杂的Shell命令
     * @param cmd
     */
    public void execCmd(String cmd){
        before();
        Session session = null;
        try {
            session = connection.openSession();
            // 建立虚拟终端
            session.requestPTY("bash");
            // 打开一个Shell
            session.startShell();
            // 准备输入命令
            PrintWriter out = new PrintWriter(session.getStdin());
            // 输入待执行命令
            out.println(cmd);
            out.println("exit");
            // 关闭输入流
            out.close();
            // 等待,除非1.连接关闭;2.输出数据传送完毕;3.进程状态为退出;4.超时
            session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 30000);
        } catch (Exception e) {
            log.error("SCP-执行shell命令失败",e);
        } finally {
            if (Objects.nonNull(session)){
                session.close();
            }
        }
    }

    /**
     * 下载到本地硬盘
     *
     * @param remoteFile 远程文件绝对路径 如:/home/users/error.txt
     * @param localPath 下载本地目录 如:C://Downloads//
     */
    public void getFile(String remoteFile, String localPath) {
        try {
            before();
            SCPClient scpClient = connection.createSCPClient();
            scpClient.get(remoteFile, localPath);
        } catch (Exception e) {
            log.error("SCP-下载到本地文件失败",e);
        } finally {
            connection.close();
        }
    }

    /**
     * 下载到字节流
     *
     * @param remoteFile 远程文件绝对路径 如:/home/users/error.txt
     */
    public ByteArrayOutputStream getFile(String remoteFile) {
        try {
            before();
            SCPClient scpClient = connection.createSCPClient();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            scpClient.get(remoteFile, outputStream);
            return outputStream;
        } catch (Exception e) {
            log.error("SCP-下载到字节流失败",e);
        } finally {
            connection.close();
        }
        return null;
    }

    /**
     * 本地硬盘文件上传
     *
     * @param localFile 本地硬盘文件目录
     * @param remoteTargetDirectory   上传的目录
     */
    public void putFile(String localFile,
                        String remoteTargetDirectory) throws RuntimeException {
        try {
            before();
            execCmd("mkdir -p " + remoteTargetDirectory);
            SCPClient scpClient = connection.createSCPClient();
            scpClient.put(localFile, remoteTargetDirectory);
        } catch (Exception e){
            log.error("SCP-上传本地文件失败",e);
            throw new RuntimeException(e);
        } finally {
            connection.close();
        }
    }

    /**
     * form表单文件上传
     *
     * @param multipartFile 表单文件
     * @param remoteTargetDirectory  上传的目录
     */
    public void putFile(@Nonnull MultipartFile multipartFile,
                        String newFileName ,
                        @Nonnull String remoteTargetDirectory) throws RuntimeException{
        try {
            before();
            execCmd("mkdir -p " + remoteTargetDirectory);
            SCPClient scpClient = connection.createSCPClient();
            InputStream inputStream = multipartFile.getInputStream();
            newFileName = StringUtils.isBlank(newFileName) ? multipartFile.getOriginalFilename() : newFileName;
            scpClient.put(IOUtils.toByteArray(inputStream), newFileName, remoteTargetDirectory);
        } catch (Exception e){
            log.error("SCP-上传本地文件失败",e);
            throw new RuntimeException(e);
        } finally {
            connection.close();
        }
    }


    /**
     * 输入流上传
     *
     * @param inputStream 输入流
     * @param remoteFileName 远程文件名称
     * @param remoteTargetDirectory 上传的目录
     */
    public void putFile(@Nonnull InputStream inputStream,
                        @Nonnull String remoteFileName,
                        @Nonnull String remoteTargetDirectory) throws RuntimeException{
        try {
            before();
            execCmd("mkdir -p " + remoteTargetDirectory);
            SCPClient scpClient = connection.createSCPClient();
            scpClient.put(IOUtils.toByteArray(inputStream), remoteFileName, remoteTargetDirectory);
        } catch (Exception e){
            log.error("SCP-上传本地文件失败",e);
            throw new RuntimeException(e);
        } finally {
            connection.close();
        }
    }
}


测试

@Slf4j
@SpringBootTest
public class ScpTests {

    @Autowired
    private ScpHelper scpHelper;

    @Test
    public void testUpload() throws IOException {
        ByteArrayInputStream bais = getTextBAIS("你好,scp!6666");
        scpHelper.putFile(bais,"266.txt","/opt/test/2021/");
    }

    public static ByteArrayInputStream getTextBAIS(String txtStr){
        try {
            byte[] bytes = txtStr.getBytes("UTF-8");
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            return inputStream;
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }
}

效果:

文件打开显示:

你好,scp!6666

参考:

java 远程执行Shell命令-通过ganymed-ssh2连接
通过java程序实现scp上传和下载文件

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java远程访问linux服务器操作 远程执行shll脚本或者命令上传下载文件 package com.szkingdom.kfit.bank.ccbDirectShortcut.helper; import ch.ethz.ssh2.Connection; import ch.ethz.ssh2.SCPClient; import ch.ethz.ssh2.Session; import ch.ethz.ssh2.StreamGobbler; import common.Logger; import org.apache.commons.lang.StringUtils; import java.io.*; import java.util.logging.Level; /** * SCP远程访问Linux服务器读取文件 * User: boyer * Date: 17-12-7 * Time: 下午3:22 * To change this template use File | Settings | File Templates. */ public class ScpClient { //字符编码默认是utf-8 private static String DEFAULTCHART="UTF-8"; protected static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(ScpClient.class); static private ScpClient instance; private Connection conn; static synchronized public ScpClient getInstance(String IP, int port, String username, String passward) { if (instance == null) { instance = new ScpClient(IP, port, username, passward); } return instance; } public ScpClient(String IP, int port, String username, String passward) { this.ip = IP; this.port = port; this.username = username; this.password = passward; } private String ip; private int port; private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } /** * 远程登录linux的主机 * @author Ickes * @since V0.1 * @return * 登录成功返回true,否则返回false */ public Boolean login(){ boolean flg=false; try { conn = new Connection(ip); conn.connect();//连接 flg=conn.authenticateWithPassword(username, password);//认证 } catch (IOException e) { e.printStackTrace(); } return flg; } /** * 下载文件 * @param remoteFile 远程文件地址 * @param localTargetDirectory 本地目录地址 */ public void getFile(String remoteFile, String localTargetDirectory) { try { if(login()){ SCPClient client = new SCPClient(conn); client.get(remoteFile, localTargetDirectory); conn.close(); } } catch (IOException ex) { log.error(ex); } } /** * 上传文件 * @param localFile 本地目录地址 * @param remoteTargetDirectory 远程目录地址 */ public void putFile(String localFile, String remoteTargetDirectory) { try { if(login()){ SCPClient client = new SCPClient(conn); client.put(localFile, remoteTargetDirectory); conn.close(); } } catch (IOException ex) { log.error(ex); } } /** * 上传文件 * @param localFile 本地目录地址 * @param remoteFileName 重命名 * @param remoteTargetDirectory 远程目录地址 * @param mode 默认0600权限 rw 读写 */ public void putFile(String localFile, String remoteFileName,String remoteTargetDirectory,String mode) { try { if(login()){ SCPClient client = new SCPClient(conn); if((mode == null) || (mode.length() == 0)){ mode = "0600"; } client.put(localFile, remoteFileName, remoteTargetDirectory, mode); //重命名 ch.ethz.ssh2.Session sess = conn.openSession(); String tmpPathName = remoteTargetDirectory +File.separator+ remoteFileName; String newPathName = tmpPathName.substring(0, tmpPathName.lastIndexOf(".")); sess.execCommand("mv " + remoteFileName + " " + newPathName);//重命名回来 conn.close(); } } catch (IOException ex) { log.error(ex); } } public static byte[] getBytes(String filePath) { byte[] buffer = null; try { File file = new File(filePath); FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream byteArray = new ByteArrayOutputStream(1024*1024); byte[] b = new byte[1024*1024]; int i; while ((i = fis.read(b)) != -1) { byteArray.write(b, 0, i); } fis.close(); byteArray.close(); buffer = byteArray.toByteArray(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return buffer; } /** * @author Ickes * 远程执行shll脚本或者命令 * @param cmd * 即将执行命令 * @return * 命令执行完后返回的结果值 * @since V0.1 */ public String execute(String cmd){ String result=""; try { if(login()){ Session session= conn.openSession();//打开一个会话 session.execCommand(cmd);//执行命令 result=processStdout(session.getStdout(),DEFAULTCHART); //如果为得到标准输出为空,说明脚本执行出错了 if(StringUtils.isBlank(result)){ result=processStdout(session.getStderr(),DEFAULTCHART); } conn.close(); session.close(); } } catch (IOException e) { e.printStackTrace(); } return result; } /** * @author Ickes * 远程执行shll脚本或者命令 * @param cmd * 即将执行命令 * @return * 命令执行成功后返回的结果值,如果命令执行失败,返回空字符串,不是null * @since V0.1 */ public String executeSuccess(String cmd){ String result=""; try { if(login()){ Session session= conn.openSession();//打开一个会话 session.execCommand(cmd);//执行命令 result=processStdout(session.getStdout(),DEFAULTCHART); conn.close(); session.close(); } } catch (IOException e) { e.printStackTrace(); } return result; } /** * 解析脚本执行返回的结果集 * @author Ickes * @param in 输入流对象 * @param charset 编码 * @since V0.1 * @return * 以纯文本的格式返回 */ private String processStdout(InputStream in, String charset){ InputStream stdout = new StreamGobbler(in); StringBuffer buffer = new StringBuffer();; try { BufferedReader br = new BufferedReader(new InputStreamReader(stdout,charset)); String line=null; while((line=br.readLine()) != null){ buffer.append(line+"\n"); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return buffer.toString(); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值