Java遠程執行Shell命令

1. Jar包:ganymed-ssh2-build210.jarweb

2. 步驟:算法

  a) 鏈接:bash

    Connection conn = new Connection(ipAddr);session

    conn.connect();app

  b)認證:ssh

    boolean authenticateVal = conn.authenticateWithPassword(userName, password);ide

     c) 打開一個Session: oop

    if(authenticateVal)ui

      Session session = conn.openSession();spa

  d) 執行Shell命令:

       1)如果執行簡單的Shell命令:(如 jps 、last 這樣的命令 )

        session.execCommand(cmd);

       2) 遇到問題:

          用方法execCommand執行Shell命令的時候,會遇到獲取不全環境變量的問題,

          好比執行 hadoop fs -ls 可能會報找不到hadoop 命令的異常

          試着用execCommand執行打印環境變量信息的時候,輸出的環境變量不完整

          與Linux主機創建鏈接的時候會默認讀取環境變量等信息

          多是由於session剛剛創建尚未讀取完默認信息的時候,execCommand就執行了Shell命令

        解決:

        因此換了另一種方式來執行Shell命令:

          // 創建虛擬終端

          session.requestPTY("bash");

          // 打開一個Shell

          session.startShell();

          // 準備輸入命令

          PrintWriter out = new PrintWriter(session.getStdin());
                
                     // 輸入待執行命令

          out.println(cmd);

          out.println("exit")

          // 6. 關閉輸入流

          out.close();

            // 7. 等待,除非1.鏈接關閉;2.輸出數據傳送完畢;3.進程狀態爲退出;4.超時

          session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 30000);       

        用這種方式執行Shell命令,會避免環境變量讀取不全的問題,第7步裏有許多標識能夠用,好比當exit命令執行後或者超過了timeout時間,則session關閉                 

        這裏須要注意,當一個Shell命令執行時間過長時,會遇到ssh鏈接超時的問題,

        解決辦法:

          1. 以前經過把Linux主機的sshd_config的參數ClientAliveInterval設爲60,同時將第7步中timeout時間設置很大,來保證命令執行完畢,

            由於是執行Mahout中一個聚類算法,耗時最少七、8分鐘,數據量大的話,須要幾個小時。

          2.  後來將命令改爲了nohup的方式執行,nohup hadoop jar .... >> XXX.log && touch XXX.log.end &

            這種方式是提交到後臺執行,即便當前鏈接斷開也會繼續執行,把命令的輸出結果寫入日誌,若是hadoop命令執行成功,則生成.end文件

            獲取文件的方法 ganymed-ssh2-build210.jar 也提供了,以下

              SCPClient scpClient = con.createSCPClient(); 

              scpClient.get("remoteFiles","localDirectory");  //從遠程獲取文件

   e) 獲取Shell命令執行結果:

    InputStream stderr = new StreamGobbler(session.getStderr());

    InputStream in = new StreamGobbler(session.getStdout());

 1 private String processStdErr(InputStream in, String charset)
 2             throws IOException {
 3         BufferedReader br = new BufferedReader(new InputStreamReader(in, charset));
 4         StringBuffer sb = new StringBuffer();
 5         
 6         if (in.available() != 0) {
 7             while (true) {
 8                 String line = br.readLine();
 9                 if (line == null)
10                     break;
11                 sb.append(line).append(System.getProperty("line.separator"));
12             }
13         }
14         
15         return sb.toString();
16     }
獲取流中數據
相關文章
相關標籤/搜索