Java进程在linux后台运行时停止

Java进程在linux后台运行时停止,java,linux,process,Java,Linux,Process,我有下面几行代码` private String build(String command) { ShellExecutable obj = new ShellExecutable(); String output = obj.executeCommand(command); return output; } private String executeCommand(String command) { Strin

我有下面几行代码`

private String build(String command) {
        ShellExecutable obj = new ShellExecutable();
        String output = obj.executeCommand(command);
        return output;
    }

    private String executeCommand(String command) {
        StringBuffer output = new StringBuffer();
        Process p;
        String[] cmdarray = { "bash", "-c", command };
        try {
            System.out.println("Before Command Execution in Bash..& command is: " + command);
            p = Runtime.getRuntime().exec(cmdarray);
            System.out.println("After Command execution in Bash & Before waitFor..");
            p.waitFor();
            System.out.println("After wait for:  " + p.exitValue());
            System.out.println("After wait for:  " + p.isAlive());
            System.out.println("After Command execution in Bash..");
            if (p.getInputStream() != null) {
                System.out.println("Input Stream is present");
                BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    output.append(line + "\n");
                }
            }

            if (p.getErrorStream() != null) {
                System.out.println("Error Stream is present");
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                String errorLine = "";
                while ((errorLine = errorReader.readLine()) != null) {
                    output.append(errorLine + "\n");
                }
            }
        } catch (Exception e) {
            System.out.println("Exception Occured:" + e.getLocalizedMessage() + "Message is:" + e.getMessage());
        }
        return output.toString();
    }
`

我尝试在Linux中作为前台进程运行它,它工作得非常出色。但是,当我尝试使用nohup运行与后台进程相同的进程时,服务正在停止。我在堆栈溢出上发现了类似的问题,但我无法找到针对这种特殊情况的解决方案

对于上述代码,我得到的输出如下:

称为listApps

在Bash中执行命令之前..&命令为:xxxxxxxx

在Bash中执行命令后&waitFor.之前

[1] +停止nohup java-jar ReadingShell-0.0.1-SNAPSHOT-jar-with-dependencies.jar

我在上面的代码中没有得到任何异常,它只是停止而没有显示任何内容。但是,当我尝试在p.waitFor()之前显示p.exitValue()时,我打印了stacktrace,如下所示

java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:424)
at org.monitoring.ReadingShell.ShellExecutable.executeCommand(ShellExecutable.java:101)
at org.monitoring.ReadingShell.ShellExecutable.build(ShellExecutable.java:82)
at org.monitoring.ReadingShell.ShellExecutable.getApplicationList(ShellExecutable.java:46)
at spark.RouteImpl$1.handle(RouteImpl.java:72)
at spark.http.matching.Routes.execute(Routes.java:61)
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
通过阅读
UnixProcess
的opendjk,我们可以看到以下内容

public synchronized int waitFor() throws InterruptedException {
    while (!hasExited) {
        wait();
    }
    return exitcode;
}

public synchronized int exitValue() {
    if (!hasExited) {
        throw new IllegalThreadStateException("process hasn't exited");
    }
    return exitcode;
}
hasExited
永远不会在文件中重置,因此在调用
waitFor()
后,逻辑上无法抛出
exitValue()。(除非被打断)


当您运行它时,与您的问题所在的代码中的内容一定有所不同。一个最小的完整示例类可以显示问题,以便我们可以重现它。在等待子进程结束之前,您必须读取输出流。否则,如果子进程向其中一个流写入的缓冲区值(512B?4K?)超过一个缓冲区的值,则会使其等待,直到有东西读取并清空缓冲区。但这不会发生,因为父进程已经在执行
waitFor()


因此,您必须创建两个线程来读取这些输出流,并在调用
waitFor()

之前启动它们。我遇到了类似的问题。如果在前台运行jar文件就可以了,但是在nohup中执行时停止,进程/作业进入停止状态

如果任何内部脚本试图从终端读取,nohup将进入stopped状态,请参阅文章


我使用tmux来解决这个问题,正如线程所建议的那样

也打印p的值,用try-catch包装整个过程并转储异常我尝试过,异常是:异常发生了:进程没有退出在问题marged中提供堆栈跟踪,这是什么意思?我向您提供了在不调用p.waitFor()的情况下尝试访问p的出口值时得到的异常;异常具有名称和堆栈跟踪,您提供的内容不完整。从一开始就值得一提的是stacktrace和错误Nope,与上面的代码相同。删除所有print语句并在前台运行,然后使用nohup运行它。它失败了。@Cheater你能用一个完整的类来更新你的问题吗?这个类用最小的代码来复制错误?很抱歉,我不能更新整个类。但是,我共享的代码与shell进程有关。您所需要做的就是将shell命令传递给build方法。@checker正如您在上面的代码中看到的,如果您在前面的行中调用waitFor(),exitValue()就不可能抛出非法的ThreadStateException。你的问题遗漏了一些东西我想说这才是真正的问题