• 【Jsch】使用SSH协议连接到远程Shell执行脚本



    如果大家熟悉Linux的话,一定对ssh,sftp,scp等命令非常熟悉,ssh是一个安全协议,用来在不同系统或者服务器之间进行安全连接,SSH 在连接和传送的过程中会加密所有的数据。
    但是SSH一般是基于客户端的或者Linux命令行的,比如客户端的工具:OpenSSH,putty,SSH Tectia;
    在linux上大家可以通过ssh username@host连接到所要想连接的主机。
    但是如果在J2EE中,如何实现SSH呢?进而可以实现SCP,SFTP的功能呢?下面介绍的JSCH就可以实现下边的功能。
    JSCH是一个纯粹的用java实现SSH功能的java  library;

    maven依赖
    1. <dependency>
    2. <groupId>com.jcraft</groupId>
    3. <artifactId>jsch</artifactId>
    4. <version>0.1.44</version>
    5. </dependency>

    关键类介绍

    • JSch:  作为中心配置点,以及Session的工厂;
     This class serves as a central configuration point, and as a factory for Session objects configured with these settings.
    1. Use getSession to start a new Session.
    2. Use one of the addIdentity methods for public-key authentication.
    3. Use setKnownHosts to enable checking of host keys.
    4. See setConfig for a list of configuration options.

    • Session:表示到远程SSH服务器的一个连接,可以包含多个Channels;
     A Session represents a connection to a SSH server.One session can contain multiple Channels of various types
    A session is opened with connect() and closed with disconnect().

    • Channel :  与Session相关联的通道,有多种不同类型;
    The abstract base class for the different types of channel which may be associated with a Session.
    1. shell - ChannelShell :A channel connected to a remote shell (本次使用的Channel)
    2. exec - ChannelExec :A channel connected to a remotely executing program
    3. direct-tcpip - ChannelDirectTCPIP: A Channel which allows forwarding a pair of local streams to/from a TCP-connection to a server on the remote side
    4. sftp - ChannelSftp :A Channel connected to an sftp server (as a subsystem of the ssh server).
    5. subsystem - ChannelSubsystem :A channel connected to a subsystem of the server process

    使用步骤

    使用Jsch进行SSH连接的具体步骤如下:
    • 步骤1: 使用Jsch获取Session: jsch.getSession()
    • 步骤2: 设置Session的password和属性等: setPassword()/setConfig();
    • 步骤3: 设置SocketFactory(可以不进行设置,使用默认的TCP socket);
    • 步骤4: 打开Session连接:connect();
    • 步骤5: 打开并连接Channel:openChannel()/connect();
    • 步骤6: 获取Channel的inputStream和outputStream,执行指定cmd或其他;
    1.   getInputStream():  All data arriving in SSH_MSG_CHANNEL_DATA messages from the remote side can be read from this stream
    2.   getOutputStream():  All data written to this stream will be sent in SSH_MSG_CHANNEL_DATA messages to the remote side.
    • 步骤7: 关闭各种资源:输入输出流/Session/Channel等;

    创建Session,并打开Session连接

    步骤1~步骤4:程序如下

    使用SSH协议,连接到Linux,执行指定命令,并获取结果

    步骤5~步骤6:程序如下

    执行Shell命令,并获取执行结果

    测试程序





    完整程序

    JSCHUtil.java

    1. package com.sssppp.Communication;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. import java.io.OutputStream;
    5. import java.net.InetAddress;
    6. import java.net.InetSocketAddress;
    7. import java.net.Socket;
    8. import java.net.UnknownHostException;
    9. import java.util.Properties;
    10. import com.jcraft.jsch.JSch;
    11. import com.jcraft.jsch.JSchException;
    12. import com.jcraft.jsch.Session;
    13. import com.jcraft.jsch.SocketFactory;
    14. /**
    15. * 相关链接: JSCH apihttp://epaul.github.io/jsch-documentation/javadoc/ Example:
    16. * http://www.jcraft.com/jsch/examples/
    17. *
    18. * @author xxxx
    19. *
    20. */
    21. public class JSCHUtil {
    22. private static JSch jsch = new JSch();
    23. /**
    24. * 创建Session,并打开Session连接
    25. *
    26. * @param dstIp
    27. * @param dstPort
    28. * @param localIp
    29. * @param localPort
    30. * @param userName
    31. * @param password
    32. * @param timeOut
    33. * @return
    34. * @throws JSchException
    35. */
    36. public static Session createSession(String dstIp, int dstPort,
    37. final String localIp, final int localPort, String userName,
    38. String password, final int timeOut) throws JSchException {
    39. //jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
    40. // A Session represents a connection to a SSH server
    41. Session session = jsch.getSession(userName, dstIp, dstPort);
    42. session.setPassword(password);
    43. Properties sshConfig = new Properties();
    44. sshConfig.put("StrictHostKeyChecking", "no");//To skip host-key check
    45. session.setConfig(sshConfig);
    46. // this socket factory is used to create a socket to the target host,
    47. // and also create the streams of this socket used by us
    48. session.setSocketFactory(new SocketFactory() {
    49. @Override
    50. public OutputStream getOutputStream(Socket socket)
    51. throws IOException {
    52. return socket.getOutputStream();
    53. }
    54. @Override
    55. public InputStream getInputStream(Socket socket) throws IOException {
    56. return socket.getInputStream();
    57. }
    58. @Override
    59. public Socket createSocket(String host, int port)
    60. throws IOException, UnknownHostException {
    61. Socket socket = new Socket();
    62. if (localIp != null) {
    63. socket.bind(new InetSocketAddress(InetAddress
    64. .getByName(localIp), localPort));
    65. }
    66. socket.connect(
    67. new InetSocketAddress(InetAddress.getByName(host), port),
    68. timeOut);
    69. return socket;
    70. }
    71. });
    72. session.connect(timeOut);
    73. return session;
    74. }
    75. }


    SSHCommUtil.java

    1. package com.sssppp.Communication;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. import java.io.OutputStream;
    5. import com.jcraft.jsch.Channel;
    6. import com.jcraft.jsch.JSchException;
    7. import com.jcraft.jsch.Session;
    8. public class SSHCommUtil {
    9. /**
    10. * 测试程序
    11. * @param args
    12. */
    13. public static void main(String[] args) {
    14. String ip = "10.180.137.241";
    15. int port = 22;
    16. String localIp = null;
    17. int localPort = 0;
    18. int timeOut = 3000;
    19. String userName = "xxx";
    20. String password = "xxx";
    21. String[] cmds = new String[] { "ifconfig | grep eth0 ",
    22. "cat /etc/redhat-release " };
    23. String[] result = null;
    24. try {
    25. result = execShellCmdBySSH(ip, port, localIp, localPort, timeOut,
    26. userName, password, cmds);
    27. } catch (Exception e) {
    28. e.printStackTrace();
    29. }
    30. if (result != null) {
    31. for (String string : result) {
    32. System.out.println(string);
    33. System.out.println("-------------------");
    34. }
    35. }
    36. }
    37. /**
    38. * 使用SSH协议,连接到Linux Shell,执行脚本命令,并获取结果
    39. *
    40. * @param dstIp
    41. * @param dstport
    42. * default :22
    43. * @param localIp
    44. * @param localPort
    45. * @param timeOut
    46. * @param userName
    47. * @param password
    48. * @param cmds
    49. * @return
    50. * @throws Exception
    51. */
    52. public static String[] execShellCmdBySSH(String dstIp, int dstport,
    53. String localIp, int localPort, int timeOut, String userName,
    54. String password, String... cmds) throws Exception {
    55. Session session = null;
    56. Channel channel = null;
    57. InputStream is = null;
    58. OutputStream os = null;
    59. try {
    60. session = JSCHUtil.createSession(dstIp, dstport, localIp,
    61. localPort, userName, password, timeOut);
    62. channel = session.openChannel("shell");
    63. // Enable agent-forwarding.
    64. // ((ChannelShell)channel).setAgentForwarding(true);
    65. // Choose the pty-type "vt102".
    66. // ((ChannelShell)channel).setPtyType("vt102");
    67. // Set environment variable "LANG" as "ja_JP.eucJP".
    68. // ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
    69. channel.connect();
    70. is = channel.getInputStream();
    71. os = channel.getOutputStream();
    72. String[] result = new String[cmds.length];
    73. for (int i = 0; i < cmds.length; i++) {
    74. result[i] = sendCommand(is, os, cmds[i]);
    75. }
    76. return result;
    77. } catch (JSchException e) {
    78. if (e.getMessage().contains("Auth fail")) {
    79. throw new Exception("Auth error");
    80. } else {
    81. throw new Exception("Connect error");
    82. }
    83. } catch (Exception e) {
    84. throw e;
    85. } finally {
    86. try {
    87. is.close();
    88. } catch (IOException e) {
    89. }
    90. try {
    91. os.close();
    92. } catch (IOException e) {
    93. }
    94. channel.disconnect();
    95. session.disconnect();
    96. }
    97. }
    98. /**
    99. * 执行Shell命令,并获取执行结果
    100. *
    101. * @param is
    102. * @param os
    103. * @param cmd
    104. * @return
    105. * @throws IOException
    106. */
    107. private static String sendCommand(InputStream is, OutputStream os,
    108. String cmd) throws IOException {
    109. os.write(cmd.getBytes());
    110. os.flush();
    111. StringBuffer sb = new StringBuffer();
    112. int beat = 0;
    113. while (true) {
    114. if (beat > 3) {
    115. break;
    116. }
    117. if (is.available() > 0) {
    118. byte[] b = new byte[is.available()];
    119. is.read(b);
    120. sb.append(new String(b));
    121. beat = 0;
    122. } else {
    123. if (sb.length() > 0) {
    124. beat++;
    125. }
    126. try {
    127. Thread.sleep(sb.toString().trim().length() == 0 ? 1000
    128. : 300);
    129. } catch (InterruptedException e) {
    130. }
    131. }
    132. }
    133. return sb.toString();
    134. }
    135. }








  • 相关阅读:
    【Office】将一个excel文件中的表移动至另一个excel中
    【 DB_Oracle】impdp/expdp导入导出dmp文件
    【DB_Oracle】设置Oracle的监听和服务随 Linux开机自启
    【DB_Oracle】Centos中安装oracle11g R2
    【 DB_Oracle】Linux下启动Oracle服务和监听程序
    【OS_Linux】VMware中给CentOS磁盘扩容
    【 OS_Linux】WinSCP实现Windows与Linux间文件的传输
    【DB_Oracle】windows下安装Oracle 11g
    鼠标键盘失灵对策(Windows8.1)
    UNIX 高手的另外 10 个习惯
  • 原文地址:https://www.cnblogs.com/ssslinppp/p/6244653.html
Copyright © 2020-2023  润新知