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

标签 java linux process

我有下面几行代码`

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 运行与后台进程相同的服务时,服务正在停止。我在堆栈溢出上发现了类似的问题,但我无法找出针对这种特殊情况的解决方案。

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

Called listApps...

Before Command Execution in Bash..& command is: xxxxxxxx

After Command execution in Bash & Before waitFor..

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

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

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)

最佳答案

您必须在等待子进程结束之前读取输出流。否则,如果 child 向其中一个流写入超过缓冲区的值(value)(512B?4K?),它将等待直到有东西读取并清空缓冲区。但这不会发生,因为您的父进程已经在执行 waitFor()

因此,您必须创建两个线程来读取这些输出流,并在调用 waitFor() 之前启动它们。

关于Java 进程在 Linux 后台运行时停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45598207/

相关文章:

java - 无法将独立的 JBoss AS7 实例配置为可从外部网络访问

linux - libusb_submit_transfer 无回调

c - 试图找出为什么子进程比应有的时间更早终止

java - 如何仅使用 eclipse 控制台中的信息来解决异常?

java - 呈现 Java JPasswordField?

c - 无法在 C 函数中将常量字符串作为参数传递

c# - 在进程终止时释放资源

ios - 使用 iOS 应用程序以编程方式终止进程? (应用商店中的示例)

c# - Java 和 C# 中的对象

java - Java ArrayList.contains() 的一些问题