如何守护 Java 程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/534648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:56:14  来源:igfitidea点击:

How to Daemonize a Java Program?

javaprocessdaemon

提问by Rich Apodaca

I have a Java program that I'd like to daemonize on a linux system. In other words, I want to start running it in a shell and have it continue running after I've logged out. I also want to be able to stop the program cleanly.

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

I found this articlewhich uses a combination of shell scripting and Java code to do the trick. It looks good, but I'd like something simpler, if possible.

我发现这篇文章结合使用了 shell 脚本和 Java 代码来解决这个问题。看起来不错,但如果可能的话,我想要更简单的东西。

What's your preferred method to daemonize a Java program on a Linux system?

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

采纳答案by Bahaa Zaid

Apache Commons Daemonwill run your Java program as Linux daemon or WinNT Service.

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

回答by John T

You could try Java Service Wrapper, the community edition is free and meets your needs.

你可以试试Java Service Wrapper,社区版是免费的,可以满足你的需求。

回答by S.Lott

I prefer the nohupcommand. The blog post says there are better ways, but I don't think they're enough better.

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

回答by Don Branson

That depends. If it's just a one-time thing, I want to daemonize it and then go home, but usually I wait for the results, I might do:

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

nohup java com.me.MyProgram &

at the command line. To kill it cleanly, you have a lot of options. You might have a listener for SIGKILL, or listen on a port and shutdown when a connection is made, periodically check a file. Difference approaches have different weaknesses. If it's for use in production, I'd give it more thought, and probably throw a script into /etc/init.d that nohups it, and have a more sophisticated shutdown, such as what tomcat has.

在命令行。要彻底杀死它,您有很多选择。您可能有一个 SIGKILL 侦听器,或者侦听端口并在建立连接时关闭,定期检查文件。不同的方法有不同的弱点。如果它用于生产,我会多考虑一下,可能会在 /etc/init.d 中添加一个脚本来对其进行 nohups,并进行更复杂的关闭,例如 tomcat 所具有的。

回答by Ben Hardy

I frequently find myself writing scripts or command lines which essentially look like this, if I want to:

如果我想,我经常发现自己编写的脚本或命令行基本上如下所示:

  1. Run a program that is immune to sighups
  2. That is completely disconnected from the shell which spawns it, and
  3. Produces a log file from stderr and stdout the contents of which are displayed as well, but
  4. Allows me to stop viewing the log in progress and do other stuff without disrupting the running process
  1. 运行一个不受 sighups 影响的程序
  2. 它与产生它的外壳完全断开,并且
  3. 从 stderr 和 stdout 生成一个日志文件,其内容也显示出来,但是
  4. 允许我停止查看正在进行的日志并执行其他操作而不中断正在运行的进程

Enjoy.

享受。

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

回答by Varkhan

If you can't rely on Java Service Wrappercited elsewhere(for instance, if you are running on Ubuntu, which has no packaged version of SW) you probably want to do it the old fashioned way: have your program write its PID in /var/run/$progname.pid, and write a standard SysV init script (use for instance the one for ntpd as an example, it's simple) around it. Preferably, make it LSB-compliant, too.

如果您不能依赖其他地方引用的Java Service Wrapper(例如,如果您在 Ubuntu 上运行,它没有打包版本的软件),您可能希望以老式的方式来做:让您的程序将其 PID 写入 / var/run/$progname.pid,并围绕它编写一个标准的 SysV init 脚本(以 ntpd 为例,它很简单)。最好也使其符合 LSB。

Essentially, the start function tests if the program is already running (by testing if /var/run/$progname.pid exists, and the contents of that file is the PID of a running process), and if not run

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

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

The stop function checks on /var/run/$progname.pid, tests if that file is the PID of a running process, verifies that it is a Java VM (so as not to kill a process that simply reused the PID from a dead instance of my Java daemon) and then kills that process.

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

When called, my main() method will start by writing its PID in the file defined in System.getProperty("pidfile").

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

One major hurdle, though: in Java, there is no simple and standard way to get the PID of the process the JVM runs in.

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

Here is what I have come up with:

这是我想出的:

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());
}

回答by dreeves

Thisquestion is about daemonizing an arbitrary program (not java-specific) so some of the answers may apply to your case:

这个问题是关于守护任意程序(不是特定于 Java 的)所以一些答案可能适用于您的情况:

回答by colini

My preferred way on Ubuntu is to use the libslack 'daemon' utility. This is what Jenkins uses on Ubuntu (which is where I got the idea.) I've used it for my Jetty-based server applications and it works well.

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

When you stop the daemon process it will signal the JVM to shutdown. You can execute shutdown/cleanup code at this point by registering a shutdown hook with Runtime.addShutdownHook().

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

回答by Velu

DaemonTools :- A cleaner way to manage services at UNIX https://cr.yp.to/daemontools.html

DaemonTools :- 一种更简洁的 UNIX 服务管理方式https://cr.yp.to/daemontools.html

  1. Install daemon tools from the url https://cr.yp.to/daemontools/install.htmlfollow the instruction mentioned there,for any issues please try instructions https://gist.github.com/rizkyabdilah/8516303

  2. Create a file at /etc/init/svscan.confand add the below lines.(only required for cent-os-6.7)

  1. 从 url https://cr.yp.to/daemontools/install.html按照那里提到的说明安装守护程序工具,对于任何问题,请尝试说明https://gist.github.com/rizkyabdilah/8516303

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

 start on runlevel [12345]
 stop on runlevel [^12345]
 respawn
 exec /command/svscanboot
 start on runlevel [12345]
 stop on runlevel [^12345]
 respawn
 exec /command/svscanboot
  1. Create a new script named runinside /service/vm/ folder and add the below lines.
  1. 在 /service/vm/ 文件夹中创建一个名为run的新脚本并添加以下行。
#!/bin/bash    
echo starting VM 
exec java -jar
/root/learning-/daemon-java/vm.jar
#!/bin/bash    
echo starting VM 
exec java -jar
/root/learning-/daemon-java/vm.jar

Note: replace the Jar with your own Jar file. or any java class file.

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

  1. Reboot the system

  2. svstat /service/vm should be up and running now !.

  3. svc -d /service/vm should bring vm down now !.
  4. svc -u /service/vm should bring vm up now !.
  1. 重新启动系统

  2. svstat /service/vm 现在应该启动并运行了!。

  3. svc -d /service/vm 现在应该关闭 vm !
  4. svc -u /service/vm 现在应该启动 vm !

回答by Oo.oO

Take a look here:

看看这里:

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

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

for a sample code that is based on JNI. In this case you daemonize the code that was started as Java and main loop is executed in C. But it is also possible to put main, daemon's, service loop inside Java.

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

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

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

Have fun with JNI!

与 JNI 一起玩得开心!