当前位置: 首页 > 知识库问答 >
问题:

通过JSch在Java上运行Linux命令

韩淇
2023-03-14

我正在通过Java上的JSch建立一个SSH连接,在我尝试运行它之前,一切似乎都很正常。sh文件。shell脚本的名称是repoidate。这很简单:

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.

现在,这是我的方法的Java代码,SSH连接试图调用同一个文件

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命令(修订版9432)上没有任何输出或执行迹象。

我想它可能在某个时候关闭了会话,没有让命令正确执行。如果updateRepo.sh文件具有类似于cptest.txttest_2.txt'的内容,它将毫无问题地执行此操作。但是我只有这个问题和其他一些特定的. sh文件。

任何帮助都将不胜感激。


共有2个答案

程俊誉
2023-03-14

这就是我所做的
我添加了执行代码2

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)

然后我试着修改更新。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路径实际上做到了这一点。非常感谢你的帮助!

竺勇
2023-03-14
匿名用户

我怀疑您的shell命令是出于某种原因出错的——也许svn不在您的路径上,也许还有其他奇怪的环境影响——但是您没有得到错误输出,因为您没有寻找它。通常,错误会在您从channelExec获得的流上发送。getErrStream但在代码中,您只从getOutputStream流中读取。

要诊断此问题,您需要获取这些错误消息。让linux使用一个流来处理常规输出和错误消息可能比让你的java程序同时从两个流中提取更容易,所以我将这一行添加为repoUpdate.sh的最上面一行:

exec 2>&1

这将导致脚本的其余部分使用正在读取的一个流作为输出和错误。

还有,就在你打电话给chanelExec之前。断开连接,在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!");
    }

如果您这样做,您应该会收到错误消息,告诉您为什么您的命令没有像您期望的那样工作。

 类似资料:
  • 我正在通过Java上的JSch建立一个SSH连接,在我尝试运行它之前,一切似乎都很正常。sh文件。shell脚本的名称是

  • 问题内容: 我有一个应用程序,该应用程序应该使用一些shell命令将文件从sdcard复制到/ system / media /。它将需要root用户,并且我正在对root用户的设备进行测试。我正在使用运行时来执行Shell命令,但无法正常工作。这是我的运行时所需要的 但是我的日志只显示其中两个没有被拒绝 这两个看起来是sysrw和sysro命令,但是当我触发此代码时,该应用程序仍会请求root权

  • 我必须将一个文件从一个位置移动到另一个位置,然后运行名为“Irel_Wrapper”的脚本 在putty中,我使用了/home/location mv filename。 所以在Java我使用通道(Exec),我能够执行上述场景,即移动文件作为mv命令是一个puty命令。 但是我不能运行脚本Irel_Wrapper(我的猜测是,因为它不是一个油灰本地命令,我不能在java与通道(Exec)。 我基

  • 问题内容: 我发现了几个用于通过Java类运行cmd命令的代码段,但我无法理解。 这是打开cmd的代码 我找到了一些其他链接来添加其他命令,例如cd http://www.coderanch.com/t/109753/Linux-UNIX/exec-command-cd-command-java 如何使用Java打开命令提示符并插入命令? 谁能帮助我了解如何CD目录,例如: 然后在该目录上运行其他

  • 我找到了几个通过Java类运行cmd命令的代码片段,但我无法理解。 这是打开命令的代码 我还找到了一些添加其他命令的链接,比如cdhttp://www.coderanch.com/t/109753/Linux-UNIX/exec-command-cd-command-java 如何使用Java打开命令提示符并插入命令? 有人能帮我了解如何cd目录,例如: 然后在该目录上运行其他命令?

  • 我正在尝试使用ProcessBuild运行cmd语句。 但是,我只能打开cmd。exe 那么如何编写此语句通过java运行cmd命令??我得到了错误,因为语句由"*"组成。如何编辑ProcessBuilder以便我可以运行语句?非常感谢