天天看点

Java程序连接Linux服务器核心组件:JSch

使用过ACS(Auto-ConfigurationServer -自动配置服务器)组件的同学都知道其核心功能是通过通过Java程序连接Linux服务器执行Shell命令、上传文件等。而通过Java程序连接Linux服务器的核心组件就是JSch(Java Secure Channel)。

JSch 是SSH2(SSH是一个安全协议,用来在不同系统或者服务器之间进行安全连接)的一个纯Java实现。它允许你连接到一个SSHD服务器,使用端口转发,X11转发进行Shell命令发送及执行,同时还可以sftp方式进行文件传输。我们可以将它的功能集成到Java程序中,从而使Java程序可以连接Linux服务器。另外该项目也提供一个J2ME版本用来在手机上直连SSHD服务器。

JSch官方地址为:http://www.jcraft.com/jsch/

GitHub 地址为:https://github.com/vngx/vngx-jsch

Java程序引入JSch组件只要通过Maven方式引入依赖:

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

JSch基础知识

JSch常用的有三种通道:ChannelShell、ChannelExec、ChannelSftp;ChannelShell和ChannelExec都用于执行命令,ChannelSftp用于上传下载文件。

1、ChannelShell和ChannelExec的区别

ChannelShell是交互式的,需要获取输出流和输入流,使用输出流发送命令,从输入流中读取命令执行的结果;

ChannelExec是非交互的,其返回的信息非常干净,只返回标准输出;

ChannelShell和ChannelExec均是输入一个字符串命令(command)进行执行,这个字符串可以包含一条或者多条shell命令,命令之间分割符不同决定了不同的返回结果:

1) 每个命令之间用";“隔开

各命令的执行结果,不会影响其它命令的执行,也就是说各个命令都会执行,但不保证每个命令都执行成功;

2) 每个命令之间用”&&“隔开

&&是并且的意思,只有前面的命令执行成功,才会去执行后面的命令;

3) 每个命令之间用”||"隔开

||是或的意思,只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止。

JSch的使用步骤

1、new一个JSch对象;

JSch jsch = new JSch();
           

2、从JSch对象中获取Session,用于连接,并设置连接信息

Session session = jsch.getSession(name, ip, port);
session.setPassword(password);
Properties config = new Properties();  
config.put("StrictHostKeyChecking", "no");  
session.setConfig(config);  
session.setTimeout(30000);
session.connect();
           

对于连接Linux有时有弹出检测提示,如下所示:

The authenticity of host '10.10.64.242' can't be established.
RSA key fingerprint is 59:0f:32:fc:7b:54:3d:90:c0:ef:5a:6b:fb:11:55:e1.
Are you sure you want to continue connecting?
           

为了跳过这个提示可以,在Session连接配置中加入配置:

Properties config = new Properties();  
config.put("StrictHostKeyChecking", "no");  
session.setConfig(config);
           

3、使用session对象调用openChannel(“xxx”)打开通信信道,并连接;

ChannelExec channel = (ChannelExec)session.openChannel("exec");    
ChannelShell channel = (ChannelShell)session.openChannel("shell");  
ChannelSftp  channel = (ChannelSftp)session.openChannel("sftp");
           

4、针对不同的channel(ChannelShell、ChannelExec、ChannelSftp)执行不同的操作

ChannelExec使用示例:

ChannelExec channel = (ChannelExec)session.openChannel("exec");    
    decorator.command(out, command);
    channel.setCommand(command);
    channel.connect();
      
    ByteArrayOutputStream errOut = new ByteArrayOutputStream();
    channel.setErrStream(errOut);
    InputStream in = channel.getInputStream();  
    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));  
    String line = null;
    Writer writer = new OutputStreamWriter(out, "UTF-8");
    while ((line = reader.readLine()) != null) {
      
      if (!getSign())
      {
        setSign(true);
        decorator.tip(out, "操作被停止");
        return;
      }
      
      line = decorator == null ? line : decorator.line(line);
      writer.write(line);
      writer.flush();
    }
    in.close();
    if(decorator != null && errOut.toByteArray().length > 0){
      decorator.error(out, new String(errOut.toByteArray(), "UTF-8"));
    }
    
    channel.disconnect();
           

ChannelShell使用示例:

ChannelShell channel = (ChannelShell)session.openChannel("shell");    
    channel.connect(3000);
    OutputStream output = channel.getOutputStream();
    decorator.command(out, command);
    output.write((command + "\n").getBytes());
    output.flush();      
      
    InputStream in = channel.getInputStream();  
    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));  
    String line = null;  
    Writer writer = new OutputStreamWriter(out, "UTF-8");
    
    try
    {
      while ((line = reader.readLine()) != null) {  
        line = decorator == null ? line : decorator.line(line);
        writer.write(line);
        writer.write("\r\n");
        writer.flush();
        for(String returnKeyWord :returnKeyWords){
          if (!getSign())
          {
            setSign(true);
            decorator.tip(out, "操作被停止");
            channel.disconnect();
            return;
          }
          
          if(line.indexOf(returnKeyWord) > -1){
            channel.disconnect();
            return;
          }
        }
      }
    }
    finally
    {
      try
      {
        if (null != in)
        {
          in.close();
        }
      }
      catch(Exception e)
      {
        
      }
      
      try
      {
        if (null != reader)
        {
          reader.close();
        }
      }
      catch(Exception e)
      {
        
      }
    }
           

ChannelSftp使用示例:

ChannelSftp  channel = (ChannelSftp)session.openChannel("sftp");    
    channel.connect();
    channel.cd(dst);
    OutputStream output = channel.put(sourceFile.getName());
    InputStream input = new FileInputStream(sourceFile);
    IOUtils.copy(input, output);
    input.close();
        output.close();
        channel.disconnect();
           

以上小编为大家介绍了JSch组件的一些概念和基本使用方法,感兴趣的同学可以动手尝试下使用JSch连接Linux服务器。后续还有更多精彩的文章,感兴趣的同学可以关注我们的微信公众号。

Java程序连接Linux服务器核心组件:JSch

继续阅读