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());
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章