2013-04-21 7 views
10

SSH를 사용하는 정적 경로 관리를위한 Java GUI 프로그램을 작성하고 있습니다. 다음과 같이 내 코드는 다음과 같습니다JSch : 세션을 유지하는 방법

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

public class Konsep { 
    String status; 
    static String username; 
    static String hostname; 
    String inputcommand; 
    String output; 
    static Session session; 

    JSch jsch = new JSch(); 

    public String status(String stringstatus) { 
     stringstatus = status; 
     return stringstatus; 
    } 

    public String InputCommand(String inputcommandstatus) { 
     inputcommandstatus = inputcommand; 
     return inputcommandstatus; 
    } 

    public void connect(String usernamelokal, String hostnamelokal, 
      String password, int port) { 
     //  JSch jsch=new JSch(); 
     try { 
      Session sessionlokal = jsch.getSession(usernamelokal, 
        hostnamelokal, port); 
      sessionlokal.setPassword(password); 
      UserInfo ui = new UserInfoku.Infoku(); 
      sessionlokal.setUserInfo(ui); 
      sessionlokal.setTimeout(0); 
      sessionlokal.connect(); 
      status = "tersambung \n"; 
      username = usernamelokal; 
      hostname = hostnamelokal; 
      session = sessionlokal; 
      System.out.println(username + " " + hostname); 
     } catch (Exception e) { 
      System.out.println(e); 
      status = "Exception = \n " + e + "\n"; 

     } 
    } 

    public void disconnect() { 
     //  JSch jsch=new JSch(); 
     try { 
      Session sessionlokal = jsch.getSession(username, hostname); 
      //   System.out.println(username +" "+ hostname); 
      sessionlokal.disconnect(); 
      status = "wes pedhoott \n"; 
     } catch (Exception e) { 
      System.out.println(e); 
      status = "Exception = \n " + e + "\n"; 
     } 

    } 

    public void addRoute() { 
     //  JSch jsch=new JSch(); 
     System.out.println(username + " " + hostname); 
     try { 
      Session sessionlokal = session; // =jsch.getSession(username, hostname); 
      Channel channel = sessionlokal.openChannel("exec"); 
      ((ChannelExec) channel).setCommand(inputcommand); 
      channel.setInputStream(null); 
      channel.connect(); 
      ((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()) { 
        System.out.println("exit-status: " 
          + channel.getExitStatus()); 
        break; 
       } 
       try { 
        Thread.sleep(1000); 
       } catch (Exception ee) { 
       } 
      } 

      channel.disconnect(); 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
}  

내가 연결 메서드를 호출 한 후 addroute를 호출 할 때 문제는, 프로그램이

root 192.168.50.2 
root 192.168.50.2 
com.jcraft.jsch.JSchException: session is down 

내가 함께 세션 상태를 얻기 위해 노력했습니다 반환하거나

Session sessionlokal=session; //returns com.jcraft.jsch.JSchException: ChannelExec 

또는

Session sessionlokal=jsch.getSession(username, hostname); //returns session is down 

나는 또한 keepalive를 사용하려고 시도했으나 작동하지 않습니다.

내 의도는 세션을 올려 놓고 명령을 실행하고 나중에 다른 명령을 실행 한 다음 필요없는 경우 (로그 아웃) 세션을 닫을 때 세션을 호스트 (로그인)하는 것입니다. 이 포럼에서 검색 한 결과이 코드는 question이지만 코드는 먼저 실행할 명령을 정의한 다음 세션을 만들고 명령의 메서드를 호출하고 세션을 닫는 메서드를 만듭니다.

위에서 언급 한 방법에 대한 아이디어가 있으십니까?

답변

10

성공하지 Session.sendKeepAliveMsg() 시도 후, 나는 오히려 안정 될 것으로 보인다 다음과 같은 솔루션에 온 :

private Session getSession() throws Exception { 
    try { 
     if (!session.isConnected()) { 
      logger.info("Session nicht konnektiert. Versuche (erneut) zu konnektieren."); 
      session.connect(); 
     } 
    } catch (Throwable t) { 
     logger.info("Session kaputt. Baue neue."); 
     session = jsch.getSession(user, host, port); 
     session.setConfig(config); 
     session.connect(); 
    } 
    return session; 
} 

업데이트 : 몇 일 후가 실패했습니다.

서버에서 열린 세션을 종료하여 테스트를 시도했습니다. 이 방법으로 테스트 한 모든 이전 버전은 며칠을 기다리거나 서버 프로세스를 종료 한 후에도 문제가 발생하지 않았기 때문에 똑같은 동작을 보였으므로이 테스트와 그 결과가 의미있는 결과라고 생각했습니다. 불행히도 그것은 아닙니다.

나는 그것을 고치고 최신으로 유지하는 다른 방법을 시도 할 것입니다.

업데이트 2 : 생산 환경에서

private Session getSession() throws Exception { 
    try { 
     ChannelExec testChannel = (ChannelExec) session.openChannel("exec"); 
     testChannel.setCommand("true"); 
     testChannel.connect(); 
     if(logger.isDebugEnabled()) { 
      logger.debug("Session erfolgreich getestet, verwende sie erneut"); 
     } 
     testChannel.exit(); 
    } catch (Throwable t) { 
     logger.info("Session kaputt. Baue neue."); 
     session = jsch.getSession(user, host, port); 
     session.setConfig(config); 
     session.connect(); 
    } 
    return session; 
} 

이 버전은 실행 몇 주 : 최종 해결책은 unelegant 및 작업을 guarateed. 하루에 한 번 정보 메시지가 기록됩니다.

채널을 열고 아무것도하지 않는 명령을 수행하는 데 드는 비용은 다소 성가시다. 그러나 세션의 상태에 대해 확실히 확신 할 수있는 다른 방법은 없다.

+0

좋은 해결책, 단지 하나의 힌트 : 나는'testChannel.exit();'를 성공적으로 검사 한 후에 추가 할 것이다. 그렇지 않으면 각 검사마다 서버 측에서 하나의 sftp-server 데몬 프로세스로 끝난다. – GWu

+0

감사.'testChannel.exit()'가 추가되었습니다. – blafasel

+0

여러 채널을 열 때 교착 상태 문제가 발생했습니다. getSession()을 synchronized로 설정하면이 문제가 해결되지만 약간의 성능 저하가 발생합니다. 어떤 부분을 동기화해야하는지 알고 있습니까? 아마도 테스트 채널 connect = disconnect? –

관련 문제