介绍一个实现ssh-2协议的java库:Ganymed SSH-2 for Java

官方地址

官方地址:http://www.ganymed.ethz.ch/ssh2/,打开页面后,如下图位置,选择一个版本下载,我以最后发布版本说明,从图中也可以看到最后一次发版是在2006年,很老的一个库了。

介绍一个实现ssh-2协议的java库:Ganymed SSH-2 for Java_第1张图片

maven依赖

		
			ch.ethz.ganymed
			ganymed-ssh2
			build210
		

如何了解这个库的使用

在这个官网上面,打开就一个页面,并没有这个库的太多说明和讲解性资料及API说明,我是翻来翻去没找到。如果需要进一步在工作中了解并使用,建议从上面的下载路径里选择最新版本下载下来,解压开,里面有源码和doc,还有一些基本使用示例。参看那些示例,和帮助文档基本就够了,感兴趣还可以研究源码。

当然了,对于不喜欢钻研的同学,可以上网搜相关资料,网上应该也有很多基本用法的代码示例吧。

示例代码

我仅提供一个基本示例代码,在注释中会说明几个需要注意的关键点,更多示例,还是建议下载发布的源码包去参考。

public class SSHSimpleInvokeDemo {

    public static void main(String[] args) throws IOException {

        String hostname = "192.168.124.13";
        String username = "root";
        String password = "123456";

        // 基本流程
        // 1. 创建连接对象
        // 2. 建立连接
        // 3. 进行身份认证
        // 4. 打开会话,执行相关命令
        // 5. 关闭连接,释放资源

        // 创建一个准备建立连接的对象,如果不指定端口,默认是22,可以构造的时候指定端口
        Connection conn = new Connection(hostname);

        // 建立连接,这个方法支持传入参数:ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout
        // verifier:验证主机秘钥的正确性
        // connectTimeout: 就是tcp连接超时,0:不超时,不能为负数
        // kexTimeout:ssh的连接超时,指的是这个方法开始调用直到密钥交换结束的时间,0:不超时,不能为负数
        conn.connect();

        // 进行身份认证,这个指的是使用账户密码的方式,如果不支持密码方式,可以采用公钥的方式等
        // 或者使用 Connection.getRemainingAuthMethods()看下支持哪些方式
        boolean isAuthenticated = conn.authenticateWithPassword(username, password);

        if (isAuthenticated == false)
            throw new IOException("Authentication failed.");

        // 下面这个地方需要注意
        // 1. 每打开一个Session只能执行一次execCommand方法
        // 2. 一个连接可以打开几次Session,服务器这边可能也是有限制的,比如OpenSSH,默认每个连接最大会话是10
        // 可以查看你的ssh 服务器配置
        Session sess = conn.openSession();
        // 如何想要一次执行多个命令,可以把命令连接起来执行如下,前面的命令执行成功就会执行后面的命令:进入用户目录,然后打印文件列表
        sess.execCommand("cd && ls -l");

        // 如何有返回内容的话,在输出流中,错误内容在错误流中
        // StreamGobbler已经实现了缓冲区,不需要额外的缓存区封装,如:BufferedOutputStream
        InputStream stdout = new StreamGobbler(sess.getStdout());
        String message = readMessage(stdout);
        System.out.println(message);

        // 如果有错误流,读取错误流,需要注意的是输入流、输出流、错误流共享缓冲区,所以别不管错误流内容
        // 不读错误流,一旦缓冲区被用尽,命令就会被阻塞,不能执行了。当然了缓冲区大小:30kb,一般也不是那么容易占满
        if (message == null) { // 如果为空,可能是错误了,也可能是像cd这种命令,输出流本身没有内容
            InputStream stderr = new StreamGobbler(sess.getStderr());
            message = readMessage(stderr);
            System.out.println(message);
        }

        // 不要太依赖下面这两个字段,判断是执行成功还是失败了,服务器不支持,这两个字段就可能为空,所以是否成功失败,参看上面
        //System.out.println("ExitCode: " + sess.getExitStatus());
        //System.out.println("signal: " + sess.getExitSignal());

        // 关闭会话
        sess.close();

        // 如果想再调用execCommand,就再调用一次conn.openSession();,打开会话
        // 如果受到服务器会话数限制,那就需要再新建一次连接了

        // 关闭连接
        conn.close();
        // 可能有同学奇怪,服务器有会话数限制,但比如我们用有些工具,如secure CRT之类工具,是可以一直进行会话的,不受最大次数限制
        // 那是因为可以选择建立交互式会话连接,这个工具包里提供的有接口
    }

    private static String readMessage(InputStream inputStream) throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            // 按行读取,按行拼接
            StringBuilder message = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                message.append(line).append(System.lineSeparator());
            }
            return message.length() > 0 ? message.toString() : null;
        }
    }
}

我在我本地执行一下,看下结果:

介绍一个实现ssh-2协议的java库:Ganymed SSH-2 for Java_第2张图片

展示了家目录下所有文件。

固定流程,只有打开会话,执行命令处的业务不太一样,因此代码实现,非常适合模板模式。

几个注意事项,看代码注释即可。

当然,这只是一个很基本的demo。我在工作中因为业务需要,根据业务场景封装了一个还凑合的ssh客户端。只是代码提交到公司仓库,所以这就不方便展示了。

其实代码量不多,但有朋友想用现成的轮子的话,我的代码不方便,但是可以推荐一个,开源项目cache cloude有用到这个库,里面有个现成封装好的模板类,最基本的场景都能满足,有需要可以直接拿来用:https://github.com/sohutv/cachecloud/blob/master/cachecloud-open-web/src/main/java/com/sohu/cache/ssh/SSHTemplate.java

文件复制

如果需要文件远程copy,这里也提供了scp协议支持的客户端和sftp客户端,都是基于ssh连接,比如scp协议,我理解的就是建立一个ssh隧道进行传输(未具体研究过,理解有误,请指正)。有需要可以看下源码中的文档说明。对于内网比较稳定,大文件了可以考虑使用scp客户端接口就行,速度也比sftp快;网络不稳定用sftp就行。当然了,至于不同场景对scp和sftp的选型不是本文重点关注的。

如下是一个使用scp客户端copy文件到远端服务器的例子,建立连接后创建一个scp客户端,很简单:

        SCPClient scpClient = conn.createSCPClient();
        scpClient.put(System.getProperty("user.dir") + File.separator + "pom.xml", "/root/test", "0776");

 

你可能感兴趣的:(------》tcp/ip,------》java,必有用处,java,ssh,Ganymed,SSH-2)