【问题标题】:Check if process is running on windows/linux检查进程是否在 windows/linux 上运行
【发布时间】:2011-04-27 04:38:58
【问题描述】:

我有一个过程

Runtime rt = Runtime.getRuntime() ;
Process p = rt.exec(filebase+port+"/hlds.exe +ip "+ip+" +maxplayers "+players+ " -game cstrike -console +port "+port+" -nojoy -noipx -heapsize 250000 +map de_dust2 +servercfgfile server.cfg +lservercfgfile +mapcyclefile mapcycle.txt +motdfile motd.txt +logsdir logs -zone 2048",null,  new File(filebase+port)) ;

我想检查这个进程是否正在运行或在崩溃的情况下已经崩溃想要重新启动它,这个进程可以有多个实例可用,具体取决于端口

我可以在 Linux 和 Windows 上跟踪这个东西吗?阅读一些关于它的文章,但这个 1 有点不同,因为它涉及多次出现,并且只需要检查一些特定的过程

【问题讨论】:

    标签: java process


    【解决方案1】:
    boolean isRunning(Process process) {
        try {
            process.exitValue();
            return false;
        } catch (Exception e) {
            return true;
        }
    }
    

    http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html#exitValue()

    【讨论】:

    • 我知道控制流不应该使用异常,但是Java并没有给我们更好的选择。
    【解决方案2】:

    您可以执行p.waitFor(),以便执行该语句的线程等待该过程完成。然后您可以立即执行清理/重新启动逻辑,因为该代码将在进程终止时执行。但是,我不确定如果进程挂起而不是死亡,这将如何工作,但这可能值得一试。顺便说一句,如果您要在生产环境中执行此操作,我建议您使用 Java Service Wrappersupervisord

    【讨论】:

    • 在这种情况下,我应该在每次启动新进程时创建一个新线程?并继续在同一个线程上投票?
    【解决方案3】:

    从 Java 8 开始,您可以这样做:

    process.isAlive()

    【讨论】:

    • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
    【解决方案4】:

    对于 Java 8 之前的代码,我使用反射和回退来捕获 IllegalThreadStateException。反射仅适用于 ProcessImpl 的实例,但这是 ProcessBuilder 返回的内容,这对我来说通常是这种情况。

        public static boolean isProcessIsAlive(@Nullable Process process) {
        if (process == null) {
            return false;
        }
        // XXX replace with Process.isAlive() in Java 8
        try {
            Field field;
            field = process.getClass().getDeclaredField("handle");
            field.setAccessible(true);
            long handle = (long) field.get(process);
            field = process.getClass().getDeclaredField("STILL_ACTIVE");
            field.setAccessible(true);
            int stillActive = (int) field.get(process);
            Method method;
            method = process.getClass().getDeclaredMethod("getExitCodeProcess", long.class);
            method.setAccessible(true);
            int exitCode = (int) method.invoke(process, handle);
            return exitCode == stillActive;
        } catch (Exception e) {
            // Reflection failed, use the backup solution
        }
        try {
            process.exitValue();
            return false;
        } catch (IllegalThreadStateException e) {
            return true;
        }
    }
    

    【讨论】:

      【解决方案5】:

      Java 5 及更高版本可以使用 java.util.concurrent.Future 处理此问题。

      Future 表示异步计算的结果。提供了检查计算是否完成、等待其完成以及检索计算结果的方法。结果只能在计算完成时使用方法 get 检索,必要时阻塞,直到它准备好。取消是通过取消方法执行的。提供了额外的方法来确定任务是正常完成还是被取消。一旦计算完成,就不能取消计算。如果您想使用 Future 来取消可取消性但不提供可用的结果,您可以声明 Future 形式的类型并返回 null 作为底层任务的结果。

      【讨论】:

      • 力图理解方法...请任何明确的解释:)
      • 在 Java 5 中,添加了一个新的功能强大的包 java.util.concurrent。通过提供知道如何以线程安全的方式有效处理不同用例的类,它使管理子流程变得更加容易。如果你需要实现一个生产者/消费者,或者一个阻塞队列,或者一个定时任务,大部分的繁重工作都已经为你完成了。 Future 类用于跟踪线程的状态,甚至在它存在时从中获取返回值。使用这个包,尤其是 Future 似乎可以为您节省很多工作。
      • ProcessFuture之间有什么联系?
      【解决方案6】:
      public class ProcessEndNotifier extends Thread
      {
          Process process;
          MyClass classThatNeedsToBeNotified;
      
          public ProcessEndNotifier(MyClass classThatNeedsToBeNotified, Process process)
          {
              this.process = process;
              this.classThatNeedsToBeNotified = classThatNeedsToBeNotified;
          }
      
          @Override
          public void run()
          {
              try {
                  process.waitFor();
              }
              catch (InterruptedException e) {
                  classThatNeedsToBeNotified.processEnded();
              }
              classThatNeedsToBeNotified.processEnded();
          }
      }
      

      现在你可以知道一个进程是否像这样运行:

      public class MyClass
      {
          boolean isProcessRunning;       
      
          public static void main(String[]args)
          {
              Process process = Runtime.getRuntime().exec("foo -bar");
              isProcessRunning = true;
              new ProcessEndNotifier(this, process).run();
          }
      
          public void processEnded()
          {
              isProcessRunning = false;
              // Or just do stuff here!
          }
      }
      

      【讨论】:

        【解决方案7】:

        在 java 9 中,您可以使用isAlive() 方法来检查进程是否仍在运行,如下所示:

        Runtime rt = Runtime.getRuntime() ;
        Process p = rt.exec(filebase+port+"/hlds.exe +ip "+ip+" +maxplayers "+players+ " -game cstrike -console +port "+port+" -nojoy -noipx -heapsize 250000 +map de_dust2 +servercfgfile server.cfg +lservercfgfile +mapcyclefile mapcycle.txt +motdfile motd.txt +logsdir logs -zone 2048",null,  new File(filebase+port)) ;
        boolean isRunning = p.toHandle.isAlive();
        

        【讨论】:

          最近更新 更多