2013-05-04 102 views
1

我写了一个程序,它只是在远程机器上运行一个命令,然后暂停。有一个程序:当我使用,只产生输出命令,如echo Hello如何使用JSch捕捉远程输入ChannelExec

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

public class JSchTest { 
    private static String readString(String prompt) {  
     if (prompt != null) { 
      System.out.println(prompt); 
     } 
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
     String input = null; 
     try { 
      input = in.readLine(); 
     } catch (IOException e) { 
      System.err.println(e); 
     }   
     return input; 
    } 

    private static boolean readBoolean(String prompt) { 
     while (true) { 
      String input = readString(prompt); 
      if (input.equalsIgnoreCase("Y") || input.equalsIgnoreCase("N")) { 
       return input.equalsIgnoreCase("Y"); 
      } else { 
       System.out.println("Enter Y or N."); 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     JSch jsch = new JSch(); 
     Session session = jsch.getSession(readString("Login:"), 
      readString("Server:"), Integer.parseInt(readString("Port:"))); 
     session.setUserInfo(
      new UserInfo() { 
       @Override 
       public String getPassphrase() { 
        return readString("Passphrase:"); 
       } 

       @Override 
       public String getPassword() { 
        return readString("Password:"); 
       } 

       @Override 
       public boolean promptPassword(String message) { 
        return readBoolean(message); 
       } 

       @Override 
       public boolean promptPassphrase(String message) { 
        return readBoolean(message); 
       } 

       @Override 
       public boolean promptYesNo(String message) { 
        return readBoolean(message); 
       } 

       @Override 
       public void showMessage(String message) { 
        System.out.println(message); 
       } 
      } 
     ); 
     session.connect(); 
     ChannelExec channel = (ChannelExec)session.openChannel("exec"); 
     InputStream in = channel.getInputStream(); 
     channel.setCommand(readString("Command:")); 
     channel.connect();   
     byte[] buffer = new byte[1024]; 
     int bytes; 
     do { 
      while (in.available() > 0) { 
       bytes = in.read(buffer, 0, 1024); 
       System.out.print(new String(buffer, 0, bytes)); 
      } 
     } while (!channel.isClosed());       
     channel.disconnect(); 
     session.disconnect();    
    }  
} 

这个程序能正常工作。但是当我试图通过诸如read VAR;echo You entered: $VAR之类的命令时,我的程序正在运行到无限循环,因为通道未关闭,正在等待输入。

好了,我得到了channel的输出流编写

 OutputStream out = channel.getOutputStream(); 

输入和取得的I/O循环看起来像这样:

 while (true) { 
      while (in.available() > 0) { 
       bytes = in.read(buffer, 0, 1024); 
       System.out.print(new String(buffer, 0, bytes)); 
      } 
      if (channel.isClosed()) { 
       break; 
      } else if (true /* channel.isWaitingForInput() */) { 
       String output = readString(null) + "\n"; 
       out.write(output.getBytes()); 
       out.flush(); 
      } 
     } 

但正如你所看到的 - 我没有关于频道另一端发生的事情的信息。是否有我现在必须提供的输入?所以我的程序随时都会要求输入,尽管不需要。

所以有一个问题 - 我怎么能知道什么时候我必须通过一个通道的输入,或者,也许,我该如何重写我的程序,以便它不仅仅运行一个命令,而且还提供一个为他们输入,在需要的时候(但最后终止)?

+0

看看我对这个问题的回答http://stackoverflow.com/questions/16298279/never-ending-of-reading-server-response-using-jsch/16319567#16319567 – Damienknight 2013-05-07 17:39:41

回答

1

通道保持打开状态,直到断开连接。当您发送退出命令并且从主机注销时,它甚至不会自动断开连接。

您需要检查channel.getExitStatus> -1。退出状态为-1,直到会话被主机关闭(通常由用户键入'exit'触发)。

一旦退出状态返回-1以外,您可以选择处理退出状态(即,它是干净退出还是出现错误)。你需要在那之后自己断开通道:

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

    channel.setInputStream(System.in); 
    channel.setOutputStream(System.out); 

    channel.connect(); 

    while (channel.getExitStatus() == -1){ 
    try{Thread.sleep(1000);}catch(Exception e){System.out.println(e);} 
    } 

    channel.disconnect(); 

通过上面的循环,任何标准输入到Java控制台将被发送到信道,一旦用户发送“退出”,通道断开。

这里有一个工作示例:Never ending of reading server response using jSch

此外,jcraft例子(实际上不密切,当你“退出”,而是一个工作,不然例子)。 http://www.jcraft.com/jsch/examples/UserAuthKI.java