|
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
- 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);
- }
- }
- }
複製代碼
運行結果:
- 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查看:
- (省略一些....)
- [root@hidden ~]# ls
- ls
- 1.txt install.log.syslog vmware-tools-distrib 模板 文档 桌面
- anaconda-ks.cfg logs workspace 视频 下载
- install.log util 公共的 图片 音乐
- [root@hidden ~]#
複製代碼
這樣就和在原linux系統中一樣使用shell功能了。
如果需要跳過如下的檢測:
- 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?
複製代碼
只需要在程序中加入相應的代碼:
- session.setConfig("StrictHostKeyChecking", "no");
複製代碼
運行結果:
- Last login: Thu Sep 29 18:39:18 2016 from 10.101.48.240
- [root@hidden ~]#
複製代碼
第二個例子:運行一條shell指令,這裡就那“ls”做例子好了。
沒有更多的話,告訴你代碼:
- 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);
- }
- }
- }
複製代碼
運行結果:
- 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端就認為是一條完整的命令了。
最後將第一個和第二個例子合併,並提取一些公用模塊,以便更好的理解和使用:
- 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) { }
- }
- }
複製代碼
測試代碼:
- 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();
複製代碼
測試結果:
- 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
|
|