2012-09-03 19 views
1

我正在使用Primefaces的終端組件和JSch ssh到遠程桌面。由於執行通道的執行需要很多時間,因爲會話和通道都在每個命令處關閉,我沒有設法解決這個問題。所以我將頻道改爲shell,現在我試圖「重定向」標準輸入/輸出隊列。這裏是我的代碼的樣子:將JSch的標準iostream重定向到primefaces終端

import org.apache.commons.io.IOUtils; 
import org.apache.commons.lang3.StringUtils; 

@ManagedBean 
@SessionScoped 
public class TerminalController implements Serializable{ 

    public TerminalController(){ 
    jsch=new JSch(); 
    InputStream in=null; 
    PrintStream out=System.out; 
try{ 
         session=jsch.getSession(user, ip, port); 
         session.setConfig("StrictHostKeyChecking", "no"); 
         session.setPassword(passwd); 
         session.connect(); 
         channel=session.openChannel("shell");  
         channel.setInputStream(in); 
         channel.setOutputStream(out); 
         channel.connect(); 
}catch(Exception ee){ 
         System.out.println(ee); 
} } 
    public String handleCommand(String command, String[] params) { 
    command=command+StringUtils.join(params," "); 

        in=IOUtils.toInputStream(command); 
        String result=out.toString(); 
        out.flush(); 
        return result;} 

我知道這是一團糟,我仍然是java的初學者。 我想到的另一個問題是,在從iostream到字符串的轉換中,我可能會失去輸入按鈕功能!我在等你的建議,解決方案和建議。

回答

0

設置in變量對通道沒有影響,並且調用out.toString()不會得到任何結果。

您需要將寫入命令(帶其參數)到通道,然後從那裏讀取輸出。另外,請不要使用setInputStreamsetOutputStream方法(如果您有現成的數據流要讀取或要寫入哪些數據流,那麼這些方法很好)。

public class TerminalController implements Serializable{ 

    BufferedReader fromChannel; 
    PrintWriter toChannel; 
    Channel channel; 
    Session session; 

    public TerminalController(){ 
     jsch=new JSch(); 
     try { 
      session=jsch.getSession(user, ip, port); 
      session.setConfig("StrictHostKeyChecking", "no"); 
      session.setPassword(passwd); 
      session.connect(); 
      channel = session.openChannel("shell");  
      InputStream inStream = channel.getInputStream(); 
      fromChannel = new BufferedReader(new InputStreamReader(inStream, "UTF-8")); 
      OutputStream outStream = channel.getOutputStream(); 
      toChannel = new PrintWriter(new OutputStreamWriter(outStream, "UTF-8")); 
      channel.connect(); 
     } catch(Exception ee) { 
      ee.printStackTrace(); 
     } 
    } 

    public String handleCommand(String command, String[] params) { 
     command = command + StringUtils.join(params," "); 
     toChannel.println(command); 
     StringBuilder result = new StringBuilder(); 
     while(true) { 
      String line = fromChannel.readLine(); 
      result.append(line); 
      if(looksLikePrompt(line)) 
       return result.toString(); 
      result.append("\n"); 
     } 
    } 
} 

難的部分,當從遠程命令的輸出完成實際上是知道的,你需要返回(這是在looksLikePrompt方法,我不知道怎麼寫)。

我不確定Primeface的終端組件的CommandHandler原理是否是創建交互式終端的正確設計,終端不需要知道命令何時完成。當命令需要更多輸入時會發生什麼?

+1

非常感謝您的回答。那麼Primefaces的終端組件不是終端仿真的明智選擇,這一事實我覺得太晚了。說實話,我喜歡它的兩件事是:個性化提示(帶有xhtml屬性)和命令歷史記錄(最多100個或更多)。 looksLikePrompt方法我可以解決,但我遇到了更大的問題。起初,我開始使用Exec頻道,但我不能重複使用相同的頻道,甚至不止一次嘗試條件結構,它不工作。我不完全瞭解JSch。 – JohnTube

+0

每個可執行通道只能使用一次(對於一個命令),但您應該可以使用同一會話。不要在各個命令之間使用session.disconnect()(之後,您需要一個新的會話)。 –

+0

我沒有使用session.disconnect()!我認爲我的代碼缺少的是Thread.sleep(n);或者,在每個命令之後,bean作用域的選擇會自動結束會話。 – JohnTube

1
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.SessionScoped; 

import org.apache.commons.lang.StringUtils; 
import org.fusesource.jansi.AnsiConsole; 
import org.fusesource.jansi.AnsiString; 

import com.jcraft.jsch.Channel; 
import com.jcraft.jsch.JSch; 
import com.jcraft.jsch.Session; 

@ManagedBean 
@SessionScoped 
public class TerminalController { 
    BufferedReader fromChannel; 
    PrintWriter toChannel; 
    Channel channel; 
    Session session; 
    JSch jsch; 

    public TerminalController() { 
     jsch = new JSch(); 
     try { 
      session = jsch.getSession("leoks", "localhost", 22); 
      session.setConfig("StrictHostKeyChecking", "no"); 
      session.setPassword("xxx"); 
      session.connect(Integer.MAX_VALUE); // 3 secs timeout 
      channel = session.openChannel("shell"); 
      InputStream inStream = channel.getInputStream(); 
      fromChannel = new BufferedReader(new InputStreamReader(inStream, 
        "UTF-8")); 
      OutputStream outStream = channel.getOutputStream(); 
      toChannel = new PrintWriter(new OutputStreamWriter(outStream, 
        "UTF-8")); 
      channel.connect(); 

      StringBuilder result = new StringBuilder(); 
      boolean stop = false; 
      while (!stop) { 
       // prompt does not end with newline... 
       char c = (char) fromChannel.read(); 
       result.append(c); 
       System.out.print(c); 
       if (result.toString().endsWith("$")) { 
        System.out.print("<<<"); 
        stop = true; 
       } 
      } 

     } catch (Exception ee) { 
      ee.printStackTrace(); 
     } 
    } 

    public String handleCommand(String command, String[] params) 
      throws IOException { 
     command = command + " " + StringUtils.join(params, " "); 
     toChannel.println(command); 
     toChannel.flush(); 
     StringBuilder result = new StringBuilder(); 
     AnsiConsole.systemInstall(); 
     while (true) { 
      char c = (char) fromChannel.read(); 
      result.append(c); 
      if (c == '$') { 
       AnsiString as = new AnsiString(result.toString()); 
       String s = as.getPlain().toString(); 
       s = s.replaceAll("\n", "<br>"); 
       AnsiConsole.systemUninstall(); 
       return s; 
      } 
     } 
    } 
} 

Jansi也有需要一些工作正常替換\ n,其中BR因爲終端組件呈現HTML和靜默忽略任何畸形字符串完全控制代碼的HTML渲染類。你也可以用固定寬度字體更換終端CSS定義,例如,使用CSS如

.ui-widget 
{ 
    font-family: "Courier New", Courier, monospace; 
    font-size: 0.8em; 
} 

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:p="http://primefaces.org/ui"> 
<h:head> 
    <title>Terminal POC</title> 
</h:head> 
<h:body> 
    <h:outputStylesheet library="css" name="styles.css" /> 
    <h:form> 
     <p:terminal 
      commandHandler="#{terminalController.handleCommand}" 
      height="300px" 
      welcomeMessage="Welcome..." 
      prompt="&gt;" /> 
    </h:form> 
</h:body> 
</html>