TShopping

 找回密碼
 註冊
搜索
查看: 288|回復: 0

[轉帖] JSch基本使用

[複製鏈接]
發表於 2019-2-20 23:04:30 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk  

JSch 是SSH2的一個純Java實現。它允許你連接到一個sshd 服務器,使用端口轉發,X11轉發,文件傳輸等等。你可以將它的功能集成到你自己的程序中。同時該項目也提供一個J2ME版本用來在手機上直連SSHD服務器。

官網: http://www.jcraft.com/jsch/中有很多例子http://www.jcraft.com/jsch/examples/,這裡先採用(已做修改)其中2個來進行簡單論述,希望對大家有所幫助。
本文采用的jsch版本是0.1.51.下載地址:http://sourceforge.net/projects/jsch/files/jsch/0.1.54/jsch-0.1.54.zip/download
本文采用的Linux操作系統是CentOS6.5.

TIPS: 查看Linux操作系統(內核)版本可以使用:uname -a; uname -r; cat /etc/issue; cat /etc/redhat-release等命令。

第一個例子:採用Java模擬shell操作。
這裡涉及到幾個參數,會在下面的代碼中有所體現:

USER:所連接的Linux主機登錄時的用戶名
PASSWORD:登錄密碼
HOST:主機地址
DEFAULT_SSH_PROT=端口號,默認為22
  1. package com.test.jsch;

  2. /**
  3. * This program enables you to connect to sshd server and get the shell prompt.
  4. * You will be asked username, hostname and passwd.
  5. * If everything works fine, you will get the shell prompt. Output may
  6. * be ugly because of lacks of terminal-emulation, but you can issue commands.
  7. */

  8. import com.jcraft.jsch.JSch;
  9. import com.jcraft.jsch.Session;
  10. import com.jcraft.jsch.UserInfo;
  11. import com.jcraft.jsch.Channel;

  12. public class Shell{
  13.     private static final String USER="root";
  14.     private static final String PASSWORD="********";
  15.     private static final String HOST="localhost";
  16.     private static final int DEFAULT_SSH_PORT=22;

  17.     public static void main(String[] arg){

  18.         try{
  19.             JSch jsch=new JSch();
  20.             Session session = jsch.getSession(USER,HOST,DEFAULT_SSH_PORT);
  21.             session.setPassword(PASSWORD);

  22.             UserInfo userInfo = new UserInfo() {
  23.                 @Override
  24.                 public String getPassphrase() {
  25.                     System.out.println("getPassphrase");
  26.                     return null;
  27.                 }
  28.                 @Override
  29.                 public String getPassword() {
  30.                     System.out.println("getPassword");
  31.                     return null;
  32.                 }
  33.                 @Override
  34.                 public boolean promptPassword(String s) {
  35.                     System.out.println("promptPassword:"+s);
  36.                     return false;
  37.                 }
  38.                 @Override
  39.                 public boolean promptPassphrase(String s) {
  40.                     System.out.println("promptPassphrase:"+s);
  41.                     return false;
  42.                 }
  43.                 @Override
  44.                 public boolean promptYesNo(String s) {
  45.                     System.out.println("promptYesNo:"+s);
  46.                     return true;//notice here!
  47.                 }
  48.                 @Override
  49.                 public void showMessage(String s) {
  50.                     System.out.println("showMessage:"+s);
  51.                 }
  52.             };

  53.             session.setUserInfo(userInfo);

  54.             // It must not be recommended, but if you want to skip host-key check,
  55.             // invoke following,
  56.             // session.setConfig("StrictHostKeyChecking", "no");

  57.             //session.connect();
  58.             session.connect(30000);   // making a connection with timeout.

  59.             Channel channel=session.openChannel("shell");

  60.             // Enable agent-forwarding.
  61.             //((ChannelShell)channel).setAgentForwarding(true);

  62.             channel.setInputStream(System.in);
  63.       /*
  64.       // a hack for MS-DOS prompt on Windows.
  65.       channel.setInputStream(new FilterInputStream(System.in){
  66.           public int read(byte[] b, int off, int len)throws IOException{
  67.             return in.read(b, off, (len>1024?1024:len));
  68.           }
  69.         });
  70.        */

  71.             channel.setOutputStream(System.out);

  72.       /*
  73.       // Choose the pty-type "vt102".
  74.       ((ChannelShell)channel).setPtyType("vt102");
  75.       */

  76.       /*
  77.       // Set environment variable "LANG" as "ja_JP.eucJP".
  78.       ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
  79.       */

  80.             //channel.connect();
  81.             channel.connect(3*1000);
  82.         }
  83.         catch(Exception e){
  84.             System.out.println(e);
  85.         }
  86.     }
  87. }
複製代碼

運行結果:

  1. promptYesNo:
  2. The authenticity of host '10.101.139.5' can't be established.
  3. RSA key fingerprint is 59:0f:32:fc:7b:54:3d:90:c0:ef:5a:6b:fb:11:55:e1.
  4. Are you sure you want to continue connecting?
  5. trueLast login: Thu Sep 29 18:40:56 2016 from 10.101.48.240
  6. [root@hidden ~]#
複製代碼

輸入ls查看:

  1. (省略一些....)
  2. [root@hidden ~]# ls
  3. ls
  4. 1.txt            install.log.syslog  vmware-tools-distrib  模板  文档  桌面
  5. anaconda-ks.cfg  logs                workspace             视频  下载
  6. install.log      util                公共的                图片  音乐
  7. [root@hidden ~]#
複製代碼

這樣就和在原linux系統中一樣使用shell功能了。

如果需要跳過如下的檢測:

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

只需要在程序中加入相應的代碼:

  1. session.setConfig("StrictHostKeyChecking", "no");
複製代碼

運行結果:

  1. Last login: Thu Sep 29 18:39:18 2016 from 10.101.48.240
  2. [root@hidden ~]#
複製代碼

第二個例子:運行一條shell指令,這裡就那“ls”做例子好了。

沒有更多的話,告訴你代碼:

  1. package com.test.jsch;

  2. import com.jcraft.jsch.*;
  3. import java.io.*;

  4. public class Exec{
  5.     private static final String USER="root";
  6.     private static final String PASSWORD="********";
  7.     private static final String HOST="localhost";
  8.     private static final int DEFAULT_SSH_PORT=22;

  9.     public static void main(String[] arg){
  10.         try{
  11.             JSch jsch=new JSch();

  12.             Session session = jsch.getSession(USER,HOST,DEFAULT_SSH_PORT);
  13.             session.setPassword(PASSWORD);

  14.             // username and password will be given via UserInfo interface.
  15.             session.setUserInfo(new MyUserInfo());
  16.             session.connect();

  17.             String command="ls";

  18.             Channel channel=session.openChannel("exec");
  19.             ((ChannelExec)channel).setCommand(command);

  20.             // X Forwarding
  21.             // channel.setXForwarding(true);

  22.             //channel.setInputStream(System.in);
  23.             channel.setInputStream(null);

  24.             //channel.setOutputStream(System.out);

  25.             //FileOutputStream fos=new FileOutputStream("/tmp/stderr");
  26.             //((ChannelExec)channel).setErrStream(fos);
  27.             ((ChannelExec)channel).setErrStream(System.err);

  28.             InputStream in=channel.getInputStream();

  29.             channel.connect();

  30.             byte[] tmp=new byte[1024];
  31.             while(true){
  32.                 while(in.available()>0){
  33.                     int i=in.read(tmp, 0, 1024);
  34.                     if(i<0)break;
  35.                     System.out.print(new String(tmp, 0, i));
  36.                 }
  37.                 if(channel.isClosed()){
  38.                     if(in.available()>0) continue;
  39.                     System.out.println("exit-status: "+channel.getExitStatus());
  40.                     break;
  41.                 }
  42.                 try{Thread.sleep(1000);}catch(Exception ee){}
  43.             }
  44.             channel.disconnect();
  45.             session.disconnect();
  46.         }
  47.         catch(Exception e){
  48.             System.out.println(e);
  49.         }
  50.     }

  51.     private static class MyUserInfo implements UserInfo{
  52.         @Override
  53.         public String getPassphrase() {
  54.             System.out.println("getPassphrase");
  55.             return null;
  56.         }
  57.         @Override
  58.         public String getPassword() {
  59.             System.out.println("getPassword");
  60.             return null;
  61.         }
  62.         @Override
  63.         public boolean promptPassword(String s) {
  64.             System.out.println("promptPassword:"+s);
  65.             return false;
  66.         }
  67.         @Override
  68.         public boolean promptPassphrase(String s) {
  69.             System.out.println("promptPassphrase:"+s);
  70.             return false;
  71.         }
  72.         @Override
  73.         public boolean promptYesNo(String s) {
  74.             System.out.println("promptYesNo:"+s);
  75.             return true;//notice here!
  76.         }
  77.         @Override
  78.         public void showMessage(String s) {
  79.             System.out.println("showMessage:"+s);
  80.         }
  81.     }
  82. }
複製代碼

運行結果:

  1. promptYesNo:The authenticity of host '10.101.139.5' can't be established.
  2. RSA key fingerprint is 59:0f:32:fc:7b:54:3d:90:c0:ef:5a:6b:fb:11:55:e1.
  3. Are you sure you want to continue connecting?
  4. 1.txt
  5. anaconda-ks.cfg
  6. install.log
  7. install.log.syslog
  8. logs
  9. util
  10. vmware-tools-distrib
  11. workspace
  12. 公共的
  13. 模板
  14. 视频
  15. 图片
  16. 文档
  17. 下载
  18. 音乐
  19. 桌面
  20. exit-status: 0
複製代碼

第二個例子相比於第一個例子來說將UserInfo採用static class的方式提取出來,這樣更直觀一點。

JSch是以多線程方式一下,所以代碼在connect後如果不disconnect channel和session,以及相關stream, 程序會一直等待,直到關閉。

需要注意的一個問題,相關的Stream和Channel是一定要關閉的,那麼應該在什麼時候來關?執行connect後,JSch接受客戶端結果需要一定的時間(以秒計),如果馬上關閉session就會發現什麼都沒接受到或內容不全。

還有一點注意,使用shell時,看到執行後沒有結果,解決辦法是在命令行後加上”\n”字符,server端就認為是一條完整的命令了。

最後將第一個和第二個例子合併,並提取一些公用模塊,以便更好的理解和使用:

  1. package com.test.jsch;

  2. import com.jcraft.jsch.*;

  3. import java.io.*;
  4. import java.util.concurrent.TimeUnit;

  5. import static java.lang.String.format;

  6. /**
  7. * Created by hidden on 2016/9/29.
  8. */
  9. public class SSHExecutor {
  10.     private static long INTERVAL = 100L;
  11.     private static int SESSION_TIMEOUT = 30000;
  12.     private static int CHANNEL_TIMEOUT = 3000;
  13.     private JSch jsch = null;
  14.     private Session session = null;

  15.     private SSHExecutor(SSHInfo sshInfo) throws JSchException {
  16.         jsch =new JSch();
  17.         session = jsch.getSession(sshInfo.getUser(),sshInfo.getHost(),sshInfo.getPort());
  18.         session.setPassword(sshInfo.getPassword());
  19.         session.setUserInfo(new MyUserInfo());
  20.         session.connect(SESSION_TIMEOUT);
  21.     }

  22.     /*
  23.     * 在这里修改访问入口,当然可以把这个方法弄到SSHExecutor外面,这里是方便操作才这么做的
  24.     * */
  25.     public static SSHExecutor newInstance() throws JSchException {
  26.         SSHInfo sshInfo = new SSHInfo("root","******","locahost",22);
  27.         return new SSHExecutor(sshInfo);
  28.     }

  29.     /*
  30.     * 注意编码转换
  31.     * */
  32.     public long shell(String cmd, String outputFileName) throws JSchException, IOException, InterruptedException {
  33.         long start = System.currentTimeMillis();
  34.         Channel channel = session.openChannel("shell");
  35.         PipedInputStream pipeIn = new PipedInputStream();
  36.         PipedOutputStream pipeOut = new PipedOutputStream( pipeIn );
  37.         FileOutputStream fileOut = new FileOutputStream( outputFileName, true);
  38.         channel.setInputStream(pipeIn);
  39.         channel.setOutputStream(fileOut);
  40.         channel.connect(CHANNEL_TIMEOUT);

  41.         pipeOut.write(cmd.getBytes());
  42.         Thread.sleep( INTERVAL );
  43.         pipeOut.close();
  44.         pipeIn.close();
  45.         fileOut.close();
  46.         channel.disconnect();
  47.         return System.currentTimeMillis() - start;
  48.     }

  49.     public int exec(String cmd) throws IOException, JSchException, InterruptedException {
  50.         ChannelExec channelExec = (ChannelExec)session.openChannel( "exec" );
  51.         channelExec.setCommand( cmd );
  52.         channelExec.setInputStream( null );
  53.         channelExec.setErrStream( System.err );
  54.         InputStream in = channelExec.getInputStream();
  55.         channelExec.connect();

  56.         int res = -1;
  57.         StringBuffer buf = new StringBuffer( 1024 );
  58.         byte[] tmp = new byte[ 1024 ];
  59.         while ( true ) {
  60.             while ( in.available() > 0 ) {
  61.                 int i = in.read( tmp, 0, 1024 );
  62.                 if ( i < 0 ) break;
  63.                 buf.append( new String( tmp, 0, i ) );
  64.             }
  65.             if ( channelExec.isClosed() ) {
  66.                 res = channelExec.getExitStatus();
  67.                 System.out.println( format( "Exit-status: %d", res ) );
  68.                 break;
  69.             }
  70.             TimeUnit.MILLISECONDS.sleep(100);
  71.         }
  72.         System.out.println( buf.toString() );
  73.         channelExec.disconnect();
  74.         return res;
  75.     }

  76.     public Session getSession(){
  77.         return session;
  78.     }

  79.     public void close(){
  80.         getSession().disconnect();
  81.     }

  82.     /*
  83.     * SSH连接信息
  84.     * */
  85.     public static class SSHInfo{
  86.         private String user;
  87.         private String password;
  88.         private String host;
  89.         private int port;

  90.         public SSHInfo(String user, String password, String host, int port) {
  91.             this.user = user;
  92.             this.password = password;
  93.             this.host = host;
  94.             this.port = port;
  95.         }

  96.         public String getUser() {
  97.             return user;
  98.         }

  99.         public String getPassword() {
  100.             return password;
  101.         }

  102.         public String getHost() {
  103.             return host;
  104.         }

  105.         public int getPort() {
  106.             return port;
  107.         }
  108.     }

  109.     /*
  110.     * 自定义UserInfo
  111.     * */
  112.     private static class MyUserInfo implements UserInfo{

  113.         @Override public String getPassphrase() { return null; }

  114.         @Override public String getPassword() { return null; }

  115.         @Override public boolean promptPassword(String s) { return false; }

  116.         @Override public boolean promptPassphrase(String s) { return false; }

  117.         @Override
  118.         public boolean promptYesNo(String s) {
  119.             System.out.println(s);
  120.             System.out.println("true");
  121.             return true;
  122.         }

  123.         @Override public void showMessage(String s) { }
  124.     }
  125. }
複製代碼

測試代碼:

  1. SSHExecutor ssh =  SSHExecutor.newInstance();
  2. System.out.println("================");
  3. long shell1 = ssh.shell("ls\n","C:\\Users\\hidden\\Desktop\\shell.txt");
  4. long shell2 = ssh.shell("pwd\n","C:\\Users\\hidden\\Desktop\\shell.txt");
  5. System.out.println("shell 1 执行了"+shell1+"ms");
  6. System.out.println("shell 2 执行了"+shell2+"ms");
  7. System.out.println("================");
  8. int cmd1 = ssh.exec("ls\n");
  9. ssh.close();
複製代碼

測試結果:
  1. The authenticity of host '10.101.139.5' can't be established.
  2. RSA key fingerprint is 59:0f:32:fc:7b:54:3d:90:c0:ef:5a:6b:fb:11:55:e1.
  3. Are you sure you want to continue connecting?
  4. true
  5. ================
  6. shell 1 执行了142ms
  7. shell 2 执行了132ms
  8. ================
  9. Exit-status: 0
  10. 1.txt
  11. anaconda-ks.cfg
  12. install.log
  13. install.log.syslog
  14. logs
  15. util
  16. vmware-tools-distrib
  17. workspace
  18. 公共的
  19. 模板
  20. 视频
  21. 图片
  22. 文档
  23. 下载
  24. 音乐
  25. 桌面
複製代碼

還有解釋查看一下左邊是否有個shell.txt以及shell.txt是否有相應的內容。
文章出處
http://www.importnew.com/22322.html

 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2019-9-16 08:07 , Processed in 0.062609 second(s), 21 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表