2011-06-20 27 views
9

因此,我有這個類使用org.apache.commons.net.telnet.TelnetClient類。它試圖發送命令並讀取響應。如何使用apache-commons-net發送終端命令時禁用回顯TelnetClient

public class AutomatedTelnetClient 
{ 
    private TelnetClient telnet = new TelnetClient(); 
    private InputStream in; 
    private PrintStream out; 
    private String prompt = "$"; 

    public AutomatedTelnetClient(String server, String user, String password) 
    { 
     try 
     { 
      EchoOptionHandler echoopt = new EchoOptionHandler(false, false, false, false); 
      telnet.addOptionHandler(echoopt); 

      // Connect to the specified server 
      telnet.connect(server, 23); 

      // Get input and output stream references 
      in = telnet.getInputStream(); 
      out = new PrintStream(telnet.getOutputStream()); 

      // Log the user on 
      readUntil("login: "); 
      write(user); 
      readUntil("Password: "); 
      write(password); 

      // Advance to a prompt 
      readUntil(prompt + " "); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void su(String password) 
    { 
     try 
     { 
      write("su"); 
      readUntil("Password: "); 
      write(password); 
      prompt = "#"; 
      readUntil(prompt + " "); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public String readUntil(String pattern) 
    { 
     try 
     { 
      char lastChar = pattern.charAt(pattern.length() - 1); 
      StringBuffer sb = new StringBuffer(); 
      boolean found = false; 
      char ch = (char) in.read(); 
      while (true) 
      { 
       System.out.print(ch); 
       sb.append(ch); 
       if (ch == lastChar) 
       { 
        if (sb.toString().endsWith(pattern)) 
        { 
         return sb.toString(); 
        } 
       } 
       ch = (char) in.read(); 
      } 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public void write(String value) 
    { 
     try 
     { 
      out.println(value); 
      out.flush(); 
      System.out.println(value); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public String sendCommand(String command) 
    { 
     try 
     { 
      write(command); 
      return readUntil(prompt + " "); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public void disconnect() 
    { 
     try 
     { 
      telnet.disconnect(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) 
    { 
     try 
     { 
      AutomatedTelnetClient telnet = new AutomatedTelnetClient(
        "...", "...", "..."); 

      System.out.println("Got Connection..."); 

      System.out.println("run command"); 
      telnet.sendCommand("ls "); 
      telnet.sendCommand("cd netConf"); 
      telnet.sendCommand("ls "); 
      telnet.sendCommand("cd lanSetup"); 
      telnet.sendCommand("ls "); 
      telnet.sendCommand("cd dhcpd"); 
      telnet.sendCommand("show interface 2"); 

      telnet.disconnect(); 
      System.out.println("DONE"); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

問題是,當我發送一個命令時,響應以各種回聲開頭。例如,當我送ls命令,這是響應我讀

[mls 
.... 

我試過在how to disable echo搜索,但似乎沒有人有答案。所以,我決定問這個社區。有誰知道如何禁用此回聲?

編輯

綜觀EchoOptionHandler源代碼混淆了我。爲什麼子協商方法只返回null

+0

也許你可以從響應中使用substring手動刪除它,不是嗎?此致,Stéphane – Snicolas

+0

我知道,但我希望圖書館有一個機制可以這樣做。 – mre

回答

5

有趣的問題。總結我的努力:我沒有得到它正常工作 但這裏是我的一些調查結果:

你不能直接寫IAC DON'T ECHO的數據通道,這是用命令和選項,如本例中做

int[] msg = {TelnetCommand.DONT,TelnetOption.ECHO}; 
telnet.sendSubnegotiation(msg); 

可以註冊telnet.registerNotifHandler(new MyNotificationHandler());連接建立

public class MyNotificationHandler implements TelnetNotificationHandler 
{ 
    @Override 
    public void receivedNegotiation(int negotiation_code, int option_code) 
    { 
    System.out.println("--->"+get(negotiation_code)+" " 
          +TelnetOption.getOption(option_code)); 
    } 

    private String get(int i) 
    { 
    if(i==TelnetNotificationHandler.RECEIVED_DO){return "RECEIVED_DO";} 
    else if(i==TelnetNotificationHandler.RECEIVED_DONT){return "RECEIVED_DONT";} 
    else if(i==TelnetNotificationHandler.RECEIVED_WILL){return "RECEIVED_WILL";} 
    else if(i==TelnetNotificationHandler.RECEIVED_WONT){return "RECEIVED_WONT";} 
    else if(i==TelnetNotificationHandler.RECEIVED_COMMAND) 
                {return "RECEIVED_COMMAND";} 
    return "UNKNOWN"; 
    } 
} 
+0

+1,感謝您的指點,但不幸的是,這隻能證明我的方向正確! – mre

3

期間調試命令默認情況下,TelnetClient表示到遠程系統,它是一個「VT100」終端。 [m是VT100轉義序列的一部分。當構建TelnetClient通過"dumb"作爲第一個參數來指示終端不支持轉義序列。所以

TelnetClient telnet = new TelnetClient("dumb"); 

更新:

它可以是遙控器上的殼提示設置爲彩色顯示。如果你運行「回聲$ PS1」你會看到什麼提示設置爲,它可能是這樣的:

\[\e]2;\[email protected]\h : \w\007\]\[\e[39m\e[0;49m\][\[\e[1;34m\]\u\[\e[0;37m\]@\[\e[0;32m\]\h\[\e[0;36m\] \[\e[0;33m\]\w\[\e[39m\e[0;49m\]]$ 

顯示我的終端作爲「[用戶@主機目錄] $」與支架上和美元符號白色,用戶藍色,主機綠色和黃色目錄。對人們都非常好,但對機器不好。

只要您登錄,發送「PS1 ='$'\ n」。這會將提示設置爲一個美元符號 ,然後是沒有任何額外序列的空間。

+1

沒有幫助。 :/ – mre

+0

@little bunny foo foo - 我添加了一個更新到我的答案 –

1

我們在使用java TelnetClient時也遇到了這個問題。 telnet服務器是否在其響應中返回發送的命令是不一致的。

我們目前正在做什麼以確保該命令未包含在響應數據中是將stty命令發送到telnet會話以關閉終端回顯。這適用於在Linux上運行Telnet服務器,如果輸入bash shell中的命令:

的stty -echo

2

Apache是​​馬車。 EchoOptionHandler(false, false, false, false)不起作用。在一個案例中,new TelnetClient("dumb")幫助了我。另一臺服務器只服從stty -echo命令。

0

telnet echo命令是一個簡單的命令,不需要子協商。嘗試:

telnet.sendCommand((byte)(TelnetCommand.DONT | TelnetOption.ECHO)); 

它適用於我。