前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | package com.test.jsch; /** ? * This program enables you to connect to sshd server and get the shell prompt. ? * You will be asked username, hostname and passwd. ? * If everything works fine, you will get the shell prompt. Output may ? * be ugly because of lacks of terminal-emulation, but you can issue commands. ? */ import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.jcraft.jsch.UserInfo; import com.jcraft.jsch.Channel; public class Shell{ ???? private static final String USER= "root" ; ???? private static final String PASSWORD= "********" ; ???? private static final String HOST= "localhost" ; ???? private static final int DEFAULT_SSH_PORT= 22 ; ???? public static void main(String[] arg){ ???????? try { ???????????? JSch jsch= new JSch(); ???????????? Session session = jsch.getSession(USER,HOST,DEFAULT_SSH_PORT); ???????????? session.setPassword(PASSWORD); ???????????? UserInfo userInfo = new UserInfo() { ???????????????? @Override ???????????????? public String getPassphrase() { ???????????????????? System.out.println( "getPassphrase" ); ???????????????????? return null ; ???????????????? } ???????????????? @Override ???????????????? public String getPassword() { ???????????????????? System.out.println( "getPassword" ); ???????????????????? return null ; ???????????????? } ???????????????? @Override ???????????????? public boolean promptPassword(String s) { ???????????????????? System.out.println( "promptPassword:" +s); ???????????????????? return false ; ???????????????? } ???????????????? @Override ???????????????? public boolean promptPassphrase(String s) { ???????????????????? System.out.println( "promptPassphrase:" +s); ???????????????????? return false ; ???????????????? } ???????????????? @Override ???????????????? public boolean promptYesNo(String s) { ???????????????????? System.out.println( "promptYesNo:" +s); ???????????????????? return true ; //notice here! ???????????????? } ???????????????? @Override ???????????????? public void showMessage(String s) { ???????????????????? System.out.println( "showMessage:" +s); ???????????????? } ???????????? }; ???????????? session.setUserInfo(userInfo); ???????????? // It must not be recommended, but if you want to skip host-key check, ???????????? // invoke following, ???????????? // session.setConfig("StrictHostKeyChecking", "no"); ???????????? //session.connect(); ???????????? session.connect( 30000 );?? // making a connection with timeout. ???????????? Channel channel=session.openChannel( "shell" ); ???????????? // Enable agent-forwarding. ???????????? //((ChannelShell)channel).setAgentForwarding(true); ???????????? channel.setInputStream(System.in); ?????? /* ?????? // a hack for MS-DOS prompt on Windows. ?????? channel.setInputStream(new FilterInputStream(System.in){ ?????????? public int read(byte[] b, int off, int len)throws IOException{ ???????????? return in.read(b, off, (len>1024?1024:len)); ?????????? } ???????? }); ??????? */ ???????????? channel.setOutputStream(System.out); ?????? /* ?????? // Choose the pty-type "vt102". ?????? ((ChannelShell)channel).setPtyType("vt102"); ?????? */ ?????? /* ?????? // Set environment variable "LANG" as "ja_JP.eucJP". ?????? ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP"); ?????? */ ???????????? //channel.connect(); ???????????? channel.connect( 3 * 1000 ); ???????? } ???????? catch (Exception e){ ???????????? System.out.println(e); ???????? } ???? } } |
運行結果:
1 2 3 4 5 6 | promptYesNo: The authenticity of host '10.101.139.5' 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? trueLast login: Thu Sep 29 18:40:56 2016 from 10.101.48.240 [root@hidden ~] # |
輸入ls查看:
1 2 3 4 5 6 7 | (省略一些....) [root@hidden ~] # ls ls 1.txt??????????? install .log.syslog? vmware-tools-distrib? 模板? 文檔? 桌面 anaconda-ks.cfg? logs??????????????? workspace???????????? 視頻? 下載 install .log????? util??????????????? 公共的??????????????? 圖片? 音樂 [root@hidden ~] # |
這樣就和在原linux系統中一樣使用shell功能了。
如果需要跳過如下的檢測:
1 2 3 | The authenticity of host '10.101.139.5' 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? |
只需要在程序中加入相應的代碼:
1 | session.setConfig( "StrictHostKeyChecking" , "no" ); |
運行結果:
1 2 | Last login: Thu Sep 29 18:39:18 2016 from 10.101.48.240 [root@hidden ~] # |
第二個例子:運行一條shell指令,這里就那“ls”做例子好了。
No more talk, show you the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | package com.test.jsch; import com.jcraft.jsch.*; import java.io.*; public class Exec{ ???? private static final String USER= "root" ; ???? private static final String PASSWORD= "********" ; ???? private static final String HOST= "localhost" ; ???? private static final int DEFAULT_SSH_PORT= 22 ; ???? public static void main(String[] arg){ ???????? try { ???????????? JSch jsch= new JSch(); ???????????? Session session = jsch.getSession(USER,HOST,DEFAULT_SSH_PORT); ???????????? session.setPassword(PASSWORD); ???????????? // username and password will be given via UserInfo interface. ???????????? session.setUserInfo( new MyUserInfo()); ???????????? session.connect(); ???????????? String command= "ls" ; ???????????? Channel channel=session.openChannel( "exec" ); ???????????? ((ChannelExec)channel).setCommand(command); ???????????? // X Forwarding ???????????? // channel.setXForwarding(true); ???????????? //channel.setInputStream(System.in); ???????????? channel.setInputStream( null ); ???????????? //channel.setOutputStream(System.out); ???????????? //FileOutputStream fos=new FileOutputStream("/tmp/stderr"); ???????????? //((ChannelExec)channel).setErrStream(fos); ???????????? ((ChannelExec)channel).setErrStream(System.err); ???????????? InputStream in=channel.getInputStream(); ???????????? channel.connect(); ???????????? byte [] tmp= new byte [ 1024 ]; ???????????? while ( true ){ ???????????????? while (in.available()> 0 ){ ???????????????????? int i=in.read(tmp, 0 , 1024 ); ???????????????????? if (i< 0 ) break ; ???????????????????? System.out.print( new String(tmp, 0 , i)); ???????????????? } ???????????????? if (channel.isClosed()){ ???????????????????? if (in.available()> 0 ) continue ; ???????????????????? System.out.println( "exit-status: " +channel.getExitStatus()); ???????????????????? break ; ???????????????? } ???????????????? try {Thread.sleep( 1000 );} catch (Exception ee){} ???????????? } ???????????? channel.disconnect(); ???????????? session.disconnect(); ???????? } ???????? catch (Exception e){ ???????????? System.out.println(e); ???????? } ???? } ???? private static class MyUserInfo implements UserInfo{ ???????? @Override ???????? public String getPassphrase() { ???????????? System.out.println( "getPassphrase" ); ???????????? return null ; ???????? } ???????? @Override ???????? public String getPassword() { ???????????? System.out.println( "getPassword" ); ???????????? return null ; ???????? } ???????? @Override ???????? public boolean promptPassword(String s) { ???????????? System.out.println( "promptPassword:" +s); ???????????? return false ; ???????? } ???????? @Override ???????? public boolean promptPassphrase(String s) { ???????????? System.out.println( "promptPassphrase:" +s); ???????????? return false ; ???????? } ???????? @Override ???????? public boolean promptYesNo(String s) { ???????????? System.out.println( "promptYesNo:" +s); ???????????? return true ; //notice here! ???????? } ???????? @Override ???????? public void showMessage(String s) { ???????????? System.out.println( "showMessage:" +s); ???????? } ???? } } |
運行結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | promptYesNo:The authenticity of host '10.101.139.5' 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? 1.txt anaconda-ks.cfg install .log install .log.syslog logs util vmware-tools-distrib workspace 公共的 模板 視頻 圖片 文檔 下載 音樂 桌面 exit -status: 0 |
第二個例子相比于第一個例子來說將UserInfo采用static class的方式提取出來,這樣更直觀一點。
JSch是以多線程方式一下,所以代碼在connect后如果不disconnect channel和session,以及相關stream, 程序會一直等待,直到關閉。
需要注意的一個問題,相關的Stream和Channel是一定要關閉的,那么應該在什么時候來關?執行connect后,JSch接受客戶端結果需要一定的時間(以秒計),如果馬上關閉session就會發現什么都沒接受到或內容不全。
還有一點注意,使用shell時,看到執行后沒有結果,解決辦法是在命令行后加上”\n”字符,server端就認為是一條完整的命令了。
最后將第一個和第二個例子合并,并提取一些公用模塊,以便更好的理解和使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | package com.test.jsch; import com.jcraft.jsch.*; import java.io.*; import java.util.concurrent.TimeUnit; import static java.lang.String.format; /** ? * Created by hidden on 2016/9/29. ? */ public class SSHExecutor { ???? private static long INTERVAL = 100L; ???? private static int SESSION_TIMEOUT = 30000 ; ???? private static int CHANNEL_TIMEOUT = 3000 ; ???? private JSch jsch = null ; ???? private Session session = null ; ???? private SSHExecutor(SSHInfo sshInfo) throws JSchException { ???????? jsch = new JSch(); ???????? session = jsch.getSession(sshInfo.getUser(),sshInfo.getHost(),sshInfo.getPort()); ???????? session.setPassword(sshInfo.getPassword()); ???????? session.setUserInfo( new MyUserInfo()); ???????? session.connect(SESSION_TIMEOUT); ???? } ???? /* ???? * 在這里修改訪問入口,當然可以把這個方法弄到SSHExecutor外面,這里是方便操作才這么做的 ???? * */ ???? public static SSHExecutor newInstance() throws JSchException { ???????? SSHInfo sshInfo = new SSHInfo("root","******","locahost",22); ???????? return new SSHExecutor(sshInfo); ???? } ???? /* ???? * 注意編碼轉換 ???? * */ ???? public long shell(String cmd, String outputFileName) throws JSchException, IOException, InterruptedException { ???????? long start = System.currentTimeMillis(); ???????? Channel channel = session.openChannel("shell"); ???????? PipedInputStream pipeIn = new PipedInputStream(); ???????? PipedOutputStream pipeOut = new PipedOutputStream( pipeIn ); ???????? FileOutputStream fileOut = new FileOutputStream( outputFileName, true); ???????? channel.setInputStream(pipeIn); ???????? channel.setOutputStream(fileOut); ???????? channel.connect(CHANNEL_TIMEOUT); ???????? pipeOut.write(cmd.getBytes()); ???????? Thread.sleep( INTERVAL ); ???????? pipeOut.close(); ???????? pipeIn.close(); ???????? fileOut.close(); ???????? channel.disconnect(); ???????? return System.currentTimeMillis() - start; ???? } ???? public int exec(String cmd) throws IOException, JSchException, InterruptedException { ???????? ChannelExec channelExec = (ChannelExec)session.openChannel( "exec" ); ???????? channelExec.setCommand( cmd ); ???????? channelExec.setInputStream( null ); ???????? channelExec.setErrStream( System.err ); ???????? InputStream in = channelExec.getInputStream(); ???????? channelExec.connect(); ???????? int res = -1; ???????? StringBuffer buf = new StringBuffer( 1024 ); ???????? byte[] tmp = new byte[ 1024 ]; ???????? while ( true ) { ???????????? while ( in.available() > 0 ) { ???????????????? int i = in.read( tmp, 0, 1024 ); ???????????????? if ( i < 0 ) break; ???????????????? buf.append( new String( tmp, 0, i ) ); ???????????? } ???????????? if ( channelExec.isClosed() ) { ???????????????? res = channelExec.getExitStatus(); ???????????????? System.out.println( format( "Exit-status: %d", res ) ); ???????????????? break; ???????????? } ???????????? TimeUnit.MILLISECONDS.sleep(100); ???????? } ???????? System.out.println( buf.toString() ); ???????? channelExec.disconnect(); ???????? return res; ???? } ???? public Session getSession(){ ???????? return session; ???? } ???? public void close(){ ???????? getSession().disconnect(); ???? } ???? /* ???? * SSH連接信息 ???? * */ ???? public static class SSHInfo{ ???????? private String user; ???????? private String password; ???????? private String host; ???????? private int port; ???????? public SSHInfo(String user, String password, String host, int port) { ???????????? this.user = user; ???????????? this.password = password; ???????????? this.host = host; ???????????? this.port = port; ???????? } ???????? public String getUser() { ???????????? return user; ???????? } ???????? public String getPassword() { ???????????? return password; ???????? } ???????? public String getHost() { ???????????? return host; ???????? } ???????? public int getPort() { ???????????? return port; ???????? } ???? } ???? /* ???? * 自定義UserInfo ???? * */ ???? private static class MyUserInfo implements UserInfo{ ???????? @Override public String getPassphrase() { return null ; } ???????? @Override public String getPassword() { return null ; } ???????? @Override public boolean promptPassword(String s) { return false ; } ???????? @Override public boolean promptPassphrase(String s) { return false ; } ???????? @Override ???????? public boolean promptYesNo(String s) { ???????????? System.out.println(s); ???????????? System.out.println( "true" ); ???????????? return true ; ???????? } ???????? @Override public void showMessage(String s) { } ???? } } |
測試代碼:
1 2 3 4 5 6 7 8 9 | SSHExecutor ssh =? SSHExecutor.newInstance(); System.out.println( "================" ); long shell1 = ssh.shell( "ls\n" , "C:\\Users\\hidden\\Desktop\\shell.txt" ); long shell2 = ssh.shell( "pwd\n" , "C:\\Users\\hidden\\Desktop\\shell.txt" ); System.out.println( "shell 1 執行了" +shell1+ "ms" ); System.out.println( "shell 2 執行了" +shell2+ "ms" ); System.out.println( "================" ); int cmd1 = ssh.exec( "ls\n" ); ssh.close(); |
測試結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | The authenticity of host '10.101.139.5' 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? true ================ shell 1 執行了142ms shell 2 執行了132ms ================ Exit-status: 0 1.txt anaconda-ks.cfg install .log install .log.syslog logs util vmware-tools-distrib workspace 公共的 模板 視頻 圖片 文檔 下載 音樂 桌面 |
還有解釋查看一下左邊是否有個shell.txt以及shell.txt是否有相應的內容。
?
?
轉自:http://www.importnew.com/22322.html