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 }