[英]Running Linux commands on Java through JSch
我在 Java 上通過 JSch 建立 SSH 連接,一切似乎都運行良好,直到我嘗試運行 this.sh 文件。 shell 腳本的名稱是repoUpdate.sh
,它非常簡單:
echo ' ****Repository update****'
echo ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'
svn update /home/cissys/repo/2.3.0
這是我在 linux 控制台上直接獲得的輸出,其中包含對命令的正確響應:
[cissys@dsatelnx5 ~]$ repoUpdate.sh
****Repository update****
Location: /home/cissys/repo/
Command: svn update /home/cissys/repo/2.3.0
At revision 9432.
現在,這是我使用 SSH 連接嘗試調用同一文件的方法的 Java 代碼
public void cmremove()
{
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
UserInfo ui = new SUserInfo(pass, null);
session.setUserInfo(ui);
session.setPassword(pass);
session.connect();
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("./repoUpdate.sh");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = reader.readLine()) != null)
{
System.out.println(++index + " : " + line);
}
channelExec.disconnect();
session.disconnect();
System.out.println("Done!");
}
catch(Exception e)
{
System.err.println("Error: " + e);
}
}
我得到的回應如下:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
Done!
BUILD SUCCESSFUL (total time: 2 seconds)
svn
命令( At revision 9432
)沒有任何輸出或執行跡象。
我認為它可能會在某個時候關閉會話,而不是讓命令正確執行。 如果updateRepo.sh`` file would've had something like
cp test.txt test_2.txt` 的內容,它會毫無問題地完成。 但我只有這個和其他一些特定的 .sh 文件有這個問題。
任何幫助,將不勝感激。
我懷疑你的 shell 命令由於某種原因出錯了——也許svn
不在你的路徑上,也許還有其他奇怪的環境影響——但你沒有得到錯誤輸出,因為你沒有在尋找它。 通常,錯誤是在您從channelExec.getErrStream
獲得的流上發送的,但在您的代碼中,您只能從getOutputStream
流中讀取。
要對此進行診斷,您將需要獲取這些錯誤消息。 讓 Linux 將一個流用於常規輸出和錯誤消息可能比讓您的 Java 程序同時從兩個流中提取更容易,所以我將這一行添加為repoUpdate.sh
的第一行:
exec 2>&1
這將導致腳本的其余部分使用您正在讀取的一個流作為輸出和錯誤。
另外,在你調用chanelExec.disconnect
之前,在你的 java 程序中你應該記錄退出狀態,然后根據它是什么改變你的“完成:”消息:
int exitStatus = channelExec.getExitStatus();
channelExec.disconnect();
session.disconnect();
if (exitStatus < 0) {
System.out.println("Done, but exit status not set!");
} else if (exitStatus > 0) {
System.out.println("Done, but with error!");
} else {
System.out.println("Done!");
}
如果這樣做,您應該會收到錯誤消息,告訴您為什么您的命令沒有按預期運行。
這就是我所做的。
我在repoUpdate.sh文件的頂部添加了exec 2>&1
並添加了那段代碼以按照@DanielMartin 的建議讀取輸出錯誤,結果如下:
public void cmremove()
{
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
UserInfo ui = new SUserInfo(pass, null);
session.setUserInfo(ui);
session.setPassword(pass);
session.connect();
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("./repoUpdate.sh");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = reader.readLine()) != null)
{
System.out.println(++index + " : " + line);
}
int exitStatus = channelExec.getExitStatus();
channelExec.disconnect();
session.disconnect();
if(exitStatus < 0){
System.out.println("Done, but exit status not set!");
}
else if(exitStatus > 0){
System.out.println("Done, but with error!");
}
else{
System.out.println("Done!");
}
}
catch(Exception e)
{
System.err.println("Error: " + e);
}
}
所以這實際上幫助了很多。 它確認該命令實際上沒有像我想的那樣正確執行。 我在我的 java 輸出中得到了這個:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
4 : ./repoUpdate.sh[6]: svn: not found [No such file or directory]
Done!
BUILD SUCCESSFUL (total time: 2 seconds)
然后我嘗試修改repoUpdate.sh文件,添加 svn 命令的絕對路徑(謝謝,@ymnk)
exec 2>&1
echo ' ****Repository update****'
echo ' Location: /home/cissys/repo/'
echo -e ' Command: svn update /home/cissys/repo/2.3.0'
/opt/subversion/bin/svn update /home/cissys/repo/2.3.0
對於我的 java,我得到了我正在尋找的東西:
run:
1 : ****Repository update****
2 : Location: /home/cissys/repo/
3 : Command: svn update /home/cissys/repo/2.3.0
4 : At revision 9443.
Done!
BUILD SUCCESSFUL (total time: 3 seconds)
我發現我通過 java 從會話中獲取的$PATH
與我直接在 linux 控制台上獲取的不一樣。 所以添加 svn 路徑實際上起到了作用。 非常感謝您的幫助!
如何使用'svn'命令的絕對路徑?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.