簡體   English   中英

通過 JSch 在 Java 上運行 Linux 命令

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM