如何守护 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
How to Daemonize a Java Program?
提问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
回答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:
如果我想,我经常发现自己编写的脚本或命令行基本上如下所示:
- Run a program that is immune to sighups
- That is completely disconnected from the shell which spawns it, and
- Produces a log file from stderr and stdout the contents of which are displayed as well, but
- Allows me to stop viewing the log in progress and do other stuff without disrupting the running process
- 运行一个不受 sighups 影响的程序
- 它与产生它的外壳完全断开,并且
- 从 stderr 和 stdout 生成一个日志文件,其内容也显示出来,但是
- 允许我停止查看正在进行的日志并执行其他操作而不中断正在运行的进程
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
回答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
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
Create a file at /etc/init/svscan.confand add the below lines.(only required for cent-os-6.7)
从 url https://cr.yp.to/daemontools/install.html按照那里提到的说明安装守护程序工具,对于任何问题,请尝试说明https://gist.github.com/rizkyabdilah/8516303
在/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
- Create a new script named runinside /service/vm/ folder and add the below lines.
- 在 /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类文件。
Reboot the system
svstat /service/vm should be up and running now !.
- svc -d /service/vm should bring vm down now !.
- svc -u /service/vm should bring vm up now !.
重新启动系统
svstat /service/vm 现在应该启动并运行了!。
- svc -d /service/vm 现在应该关闭 vm !
- 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 一起玩得开心!