java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java通过ssh连接执行shell命令,文件传输

java通过ssh连接执行shell命令,文件传输方式

作者:kaili230

这篇文章主要介绍了java通过ssh连接执行shell命令,文件传输方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

java通过ssh连接执行shell命令,文件传输

JSch 是SSH2的纯 Java 实现 。

JSch 允许您连接到 sshd 服务器并使用端口转发、X11 转发、文件传输等,可以将其功能集成到您自己的 Java 程序中。

JSch 是在BSD 风格许可下获得许可的。

JSCH 官网:http://www.jcraft.com/jsch/

在这里插入图片描述

zip文件中有很多demo.

jar为依赖jar

maven 依赖

        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>

测试代码

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.util.Properties;
@Slf4j
public class SshTest {
    private String charset = "UTF-8"; // 设置编码格式
    private static String userName = "kevin"; // 用户名
    private static String passWord= "1"; // 登录密码
    private static String host = "192.168.10.101"; // 主机IP
    private static int port = 22; //默认端口
    private static JSch jsch;
    private static Session session;
    private static ChannelSftp channelSftp;
    @BeforeAll
    public static void createConn() throws JSchException {
		JSch.setLogger(new Log4JSch()); // detail log for JSch.
        jsch = new JSch();
//        jsch = new KeyGen().keyGenTest();
        // 密钥方式
        jsch.setKnownHosts("C:\\Users\\Admin\\.ssh\\known_hosts");
//        jsch.addIdentity("~/.ssh/id_rsa", "~/.ssh/id_rsa.pub", null);
//        jsch.addIdentity("C:\\Users\\Admin\\.ssh\\id_rsa", "C:\\Users\\Admin\\.ssh\\id_rsa.pub", null);
        String privKeyPath = "C:\\Users\\Admin\\.ssh\\id_rsa";
        jsch.addIdentity(privKeyPath);
        session = jsch.getSession(userName, host, port);
        // 密码方式
//        session.setPassword(passWord);
        Properties config = new Properties();
        /*
         * 在代码里需要跳过检测。否则会报错找不到主机
         * Test ignored.
         * com.jcraft.jsch.JSchException: UnknownHostKey: 192.168.10.101. RSA key fingerprint is 10:92:98:45:d2:ea:6b:8f:c1:43:e5:df:86:e5:ae:3c
         */
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config); // 为Session对象设置properties
        int timeout = 30000;
        session.setTimeout(timeout); // 设置timeout时间
        session.connect(); // 通过Session建立与远程服务器的连接回话
        log.info("connect server host: " + host);
    }
    /**
     * 关闭连接
     */
    @AfterAll
    public static void disconnect(){
        log.info("disconnect...");
        if (channelSftp != null && channelSftp.isConnected()) {
            channelSftp.disconnect();
        }
        if(session != null && session.isConnected()){
            session.disconnect();
        }
    }
    @Test
    public void downloadFile() throws JSchException, FileNotFoundException, SftpException {
        channelSftp = (ChannelSftp) session.openChannel("sftp");
        channelSftp.connect();
        log.info("start download channel file!");
        String directory = "/tmp";
        channelSftp.cd(directory);
        String saveDir = "D:\\desktop\\"+System.currentTimeMillis()+".txt";
        File file = new File(saveDir);
        String downloadFile = "Test.java";
        channelSftp.get(downloadFile, new FileOutputStream(file));
        log.info("Download Success!");
        channelSftp.disconnect();
        log.info("end execute channel sftp!");
    }
    @Test
    public void uploadFile() throws JSchException, SftpException, FileNotFoundException {
        channelSftp = (ChannelSftp) session.openChannel("sftp");
        channelSftp.connect();
        log.info("start upload channel file!");
        String directory = "/tmp";
        channelSftp.cd(directory);
        File file = new File("D:\\desktop\\Test.java");
        channelSftp.put(new FileInputStream(file), file.getName().replace(".", System.currentTimeMillis()+"."));
        log.info("Upload Success!");
        channelSftp.disconnect();
        log.info("end execute channel sftp!");
    }
    @Test
    public void execShell() throws JSchException, IOException {
        ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
        String cmd = "pwd";
        channelExec.setCommand(cmd);         //添加传入进来的shell命令
        channelExec.setErrStream(System.err);//通道连接错误信息提示
        channelExec.connect();
        log.info("start execute channel command!");
        try(BufferedReader in = new BufferedReader(new InputStreamReader(channelExec.getInputStream()))) {
            String msg;
            log.info("start read!");
            while ((msg = in.readLine()) != null) {
                log.info("命令返回信息:{}", msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        channelExec.disconnect();
        log.info("end execute channel command!");
    }
}

JSch 详细日志实现。

JSch.setLogger(new Log4JSch());
import com.jcraft.jsch.Logger;
import java.util.HashMap;
public class Log4JSch implements Logger {
    private static HashMap<String, String> name = new HashMap();
    static {
        name.put(String.valueOf(DEBUG), "DEBUG");
        name.put(String.valueOf(INFO), "INFO");
        name.put(String.valueOf(WARN), "WARN");
        name.put(String.valueOf(ERROR), "ERROR");
        name.put(String.valueOf(FATAL), "FATAL");
    }
    @Override
    public boolean isEnabled(int i) {
        return true;
    }
    @Override
    public void log(int level, String message) {
        System.err.println(name.get(String.valueOf(level)) + ": " + message);
    }
}

问题1

com.jcraft.jsch.JSchException: invalid privatekey: [B@17f7cd29

查看id_rsa文件,内容如下

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC...
...
...
...MAECAwQF
-----END OPENSSH PRIVATE KEY-----

解决方案

Jsch好像不支持上面的私钥格式,要解决这个问题,我们可以使用ssh-keygen将私钥格式转换为RSAorpem模式,再次运行上面的程序。

$ ssh-keygen -p -f ~/.ssh/id_rsa -m pem

重新检查私钥内容,它应该以BEGIN RSA.

-----BEGIN RSA PRIVATE KEY-----
MIIG4wIBAAK...
...
...
...E428GBDI4
-----END RSA PRIVATE KEY-----

再次尝试连接正常。

Admin@DESKTOP-91JEC09 MINGW64 ~
$ ssh kevin@hadoop101
Last login: Wed Oct 20 14:28:41 2021 from 192.168.10.1
[kevin@hadoop101 ~]$ client_loop: send disconnect: Connection reset by peer
Admin@DESKTOP-91JEC09 MINGW64 ~
$ ssh-keygen -p -f C:\\Users\\Admin\\.ssh\\id_rsa -m pem
Key has comment 'Admin@DESKTOP-91JEC09'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.
Admin@DESKTOP-91JEC09 MINGW64 ~
$ ssh kevin@hadoop101
Last login: Wed Oct 20 15:43:57 2021 from 192.168.10.1

参考文档:https://mkyong.com/java/jsch-invalid-privatekey-exception/http://www.jcraft.com/jsch/

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文