Java遠程執行Shell命令


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

2. 步驟:

  a) 連接:

    Connection conn = new Connection(ipAddr);

    conn.connect();

  b)認證:

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

     c) 打開一個Session: 

    if(authenticateVal)

      Session session = conn.openSession();

  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中一個聚類算法,耗時最少7、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     }
獲取流中數據

 

 


          

          


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM