【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\n",
  22. "cat /etc/redhat-release\n" };
  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. }









免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM