2012-02-23 58 views
4

我使用SSHJ執行某些命令,我​​用這種方法,這樣做:SSHJ掛起永遠對join()方法

private Command executeCommand(String command, SSHClient client) { 
    Command commandObject = client.startSession().exec(command); 
    commandObject.join(); 
    return commandObject; 
    } 

它工作得很好,直到我執行以下命令:

cd $SOLR; nohup java -Dsolr.solr.home=./solr -DSTOP.PORT=8079 -DSTOP.KEY=stopkey -jar start.jar 2> logs/solr.log & 

在這種情況下,整個程序掛起

commandObject.join(); 

當然,它啓動的過程開始。從shell執行的同一行也會立即返回。

任何想法爲什麼以及如何克服這一點?

編輯: 同樣的情況時,我不加入(),但讀命令的系統輸出(帶有公共-IO):

IOUtils.toString(commandObject.getInputStream())) 
+0

一個想法是重定向stdin和stderr,所以在最後一個&符號前放置'2&1'可能會有所幫助。雖然,我遇到了類似的問題,但它可能不會完全解決問題。 – bstempi 2014-01-23 20:02:13

+0

糾正我的評論:這是無益的 - nohup會重定向你,如果你沒有另外指定。我注意到在這個lib中有一些線程問題;也許你遇到過一個? – bstempi 2014-01-24 17:54:59

+0

@ilfrin, 主線程塊因爲你沒有超時而調用 'commandObject.join()'。這會阻止當前線程等待通知。如果被調用的程序掛起,主線程也會掛起。 – Boyan 2016-02-16 14:20:17

回答

2

大概你正在運行的Java應用程序是一個守護進程? (或者至少在退出之前等待很長時間)

在目標機器上擁有一個專用腳本來控制守護進程的初始化/關閉,而不是依靠SSH客戶端發送正確的序列會更好的命令。這樣,腳本封裝了乾淨地啓動和停止守護進程以及需要控制它的其他應用程序所需的所有內容,只需調用此腳本即可啓動和停止,而無需知道有關記錄位置的詳細信息,啓動它所需的java命令如何後臺進程等

您可以推出自己的init風格的腳本或使用該Tanuki's Java Service Wrapper(或類似)。

0

我有同樣的問題。

我個人的建議是,只要您使用join你實際上應該設置一些超時後到期並不會永遠鎖的線程。在我的情況下使用多個命令我初始化一個Shell實例,並且,例如會做這樣的事情:

try 
{ 
      shell = session.startShell(); 
} 
catch (Exception e) 
{ 
      // failed to open 
      return; 
} 
outputStream = shell.getOutputStream(); 
outputStream.write(Strings.toUTF8ByteArray("some fast command\n")); 
outputStream.flush(); 
try { shell.join(1, TimeUnit.SECONDS); } 
catch (Exception e) {} 
outputStream.write(Strings.toUTF8ByteArray("some complex command\n")); 
outputStream.flush(); 
try { shell.join(30, TimeUnit.SECONDS); } 
catch (Exception e) {} 

希望它可能是有一些類似的問題,任何人都非常有用。