2012-09-03 2 views
1

Primefaces의 터미널 구성 요소와 JSch를 사용하여 원격 데스크톱에 ssh를 연결합니다. exec 채널을 사용하면 각 명령에서 세션과 채널이 모두 닫히고 너무 많은 시간이 걸리므로이를 처리 할 수 ​​없었습니다. 그래서 채널을 쉘로 바꿨고 표준 입력/출력 팀을 "리디렉션"하려고합니다. 내 코드는 다음과 같습니다.JSch의 표준 iostream을 primeface 터미널로 리디렉션

나는 그것이 여전히 엉망이라는 것을 알고 있습니다. 나는 여전히 자바에서 초보자입니다. 내가 생각한 또 다른 문제점은 iostream에서 string으로 변환 할 때 입력 버튼 기능을 잃어 버릴 수 있다는 것입니다! 제안, 해결책 및 조언을 기다리고 있습니다.

답변

0

변수를 설정하면 채널에 아무런 영향을 미치지 않으며 out.toString()을 호출해도 결과가 나지 않습니다.

(매개 변수와 함께) 명령을 채널에 쓰고 거기에서 출력을 읽어야합니다. 또한 setInputStream 또는 setOutputStream 메쏘드를 사용하지 마십시오. 기존의 스트림을 읽거나 쓰지 않는 경우에는 유용합니다. 원격 명령의 출력이 완료되면

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의 터미널 구성 요소의 원리가 터미널이 명령 완료 시점을 알 필요가없는 대화 형 터미널을 만드는 올바른 디자인이라고 확신하지 못합니다. 명령에 더 많은 입력이 필요한 경우 어떻게됩니까?

+1

감사에게 많은 CSS를를 사용하여, 예를 들어, 고정 폭 글꼴로 터미널 CSS 정의를 대체 할 수 있습니다. Primefaces의 터미널 구성 요소가 터미널 에뮬레이션에 현명한 선택이 아니라는 사실은 내가 너무 늦게 알아 낸 것입니다. 솔직히 내가 좋아하는 두 가지 : 개인화 할 수있는 프롬프트 (xhtml 속성 포함) 및 명령 내역 (최대 100 개 이상). looksLikePrompt 메서드 나는 그것을 해결할 수 있지만 더 큰 문제가있다. 처음에는 Exec 채널을 사용하기 시작했지만 조건부 구조를 시도한 후에도 동일한 채널과 세션을 한 번 이상 재사용 할 수는 없으며 작동하지 않았습니다. JSch를 완전히 이해하지 못했습니다. – JohnTube

+0

각 exec 채널은 한 번만 사용할 수 있지만 동일한 세션을 사용할 수 있어야합니다. 개별 명령 사이에서 session.disconnect()를 사용하지 마십시오 (그 후에 새 세션이 필요합니다). –

+0

session.disconnect()를 사용하지 않았습니다! 내 코드가 누락 된 것 같아요 Thread.sleep (n); 또는 빈 범위를 선택하면 각 명령이 끝나면 자동으로 세션이 종료됩니다. – 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 렌더링 클래스가 있습니다. 당신은 또한 당신의 대답을 같은

.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> 
관련 문제