如何守护Java程序?

时间:2009-02-10 22:58:43

标签: java process daemon

我有一个Java程序,我想在linux系统上守护进程。换句话说,我想开始在shell中运行它,并在我退出后继续运行它。我也希望能够干净地停止这个程序。

我发现this article使用shell脚本和Java代码的组合来完成这个技巧。它看起来不错,但如果可能的话,我想要更简单的东西。

在Linux系统上守护Java程序的首选方法是什么?

11 个答案:

答案 0 :(得分:38)

Apache Commons Daemon将您的Java程序作为Linux守护程序或WinNT服务运行。

答案 1 :(得分:32)

如果您不能依赖Java Service Wrapper引用elsewhere(例如,如果您运行的是Ubuntu,它没有打包的SW版本)您可能希望以旧式方式执行此操作:让您的程序在/var/run/$progname.pid中编写其PID,并编写一个标准的SysV init脚本(例如,使用ntpd的脚本作为示例,它很简单)。最好使其符合LSB标准。

本质上,start函数测试程序是否已经运行(通过测试是否存在/var/run/$progname.pid,并且该文件的内容是正在运行的进程的PID),如果没有运行< / p>

logfile=/var/log/$progname.log
pidfile=/var/run/$progname.pid
nohup java -Dpidfile=$pidfile $jopts $mainClass </dev/null > $logfile 2>&1

stop函数检查/var/run/$progname.pid,测试该文件是否是正在运行的进程的PID,验证它是否为Java VM(以免终止只重用PID的进程)从我的Java守护进程的死实例)然后杀死该进程。

调用时,我的main()方法将首先将其PID写入System.getProperty(“pidfile”)中定义的文件中。

但存在一个主要障碍:在Java中,没有简单而标准的方法来获取JVM运行的进程的PID。

以下是我的想法:

private static String getPid() {
    File proc_self = new File("/proc/self");
    if(proc_self.exists()) try {
        return proc_self.getCanonicalFile().getName();
    }
    catch(Exception e) {
        /// Continue on fall-back
    }
    File bash = new File("/bin/bash");
    if(bash.exists()) {
        ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","echo $PPID");
        try {
            Process p = pb.start();
            BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()));
            return rd.readLine();
        }
        catch(IOException e) {
            return String.valueOf(Thread.currentThread().getId());
        }
    }
    // This is a cop-out to return something when we don't have BASH
    return String.valueOf(Thread.currentThread().getId());
}

答案 2 :(得分:24)

我经常发现自己编写的脚本或命令行基本上就是这样,如果我想:

  1. 运行一个不受sighups影响的程序
  2. 这与产生它的shell完全断开,
  3. 从stderr和stdout生成日志文件,其内容也会显示,但
  4. 允许我停止查看正在进行的日志并执行其他操作而不会中断正在运行的进程
  5. 享受。

    nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &

答案 3 :(得分:14)

我更喜欢nohup命令。博客文章说有更好的方法,但我认为它们不够好。

答案 4 :(得分:5)

您可以尝试Java Service Wrapper,社区版免费且符合您的需求。

答案 5 :(得分:4)

这取决于。如果它只是一次性的事情,我想守护它然后回家,但通常我等待结果,我可能会这样做:

nohup java com.me.MyProgram &

在命令行。要彻底杀死它,你有很多选择。您可能拥有SIGKILL的侦听器,或者在建立连接时侦听端口并关闭,并定期检查文件。差异方法有不同的弱点。如果它是用于生产的话,我会更多地考虑它,并且可能会将一个脚本放入/etc/init.d中,然后将其删除,并进行更复杂的关闭,例如tomcat所拥有的。

答案 6 :(得分:4)

我在Ubuntu上的首选方法是使用libslack'守护程序'实用程序。这就是Jenkins在Ubuntu上使用的东西(这是我的想法。)我已经将它用于基于Jetty的服务器应用程序并且运行良好。

当您停止守护程序进程时,它将通知JVM关闭。您可以通过使用Runtime.addShutdownHook()注册一个关闭挂钩来执行shutdown / cleanup代码。

答案 7 :(得分:2)

This问题是关于守护任意程序(不是特定于java的),因此一些答案可能适用于您的案例:

答案 8 :(得分:2)

DaemonTools: - 在UNIX https://cr.yp.to/daemontools.html

管理服务的更简洁方法
  1. 从网址https://cr.yp.to/daemontools/install.html安装守护程序工具 按照那里提到的说明,如有任何问题,请尝试说明https://gist.github.com/rizkyabdilah/8516303

  2. /etc/init/svscan.conf 创建一个文件并添加以下行。(仅对cent-os-6.7要求)

  3.  start on runlevel [12345]
     stop on runlevel [^12345]
     respawn
     exec /command/svscanboot
    
    1. 在/ service / vm / folder中创建一个名为 run 的新脚本,并添加以下行。
    2. #!/bin/bash    
      echo starting VM 
      exec java -jar
      /root/learning-/daemon-java/vm.jar
      

      注意:    用你自己的Jar文件替换Jar。或任何java类文件。

      1. 重新启动系统

      2. svstat / service / vm现在应该正常运行!

      3. svc -d / service / vm现在应该降低vm!。
      4. svc -u / service / vm现在应该启用vm!。

答案 9 :(得分:0)

看看这里:

http://jnicookbook.owsiak.org/recipe-no-022/

表示基于JNI的示例代码。在这种情况下,你守护作为Java启动的代码,主循环在C中执行。但是也可以将main,守护进程的服务循环放在Java中。

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029

与JNI玩得开心!

答案 10 :(得分:0)

nohup java -jar {{your-jar.jar}} > /dev/null &

这可以解决问题。