我有一个Java程序,想要在Linux系统上将其守护化。也就是说,在终端启动该程序后,即使我退出登录,它仍然可以持续运行。同时,我也想能够优雅地停止这个程序。
我找到了这篇文章,其中介绍了通过Shell脚本和Java代码的组合来实现守护化的方法。这看起来不错,但如果可能的话,我希望使用更简单的方法。
你最喜欢在Linux系统上将Java程序守护化的方法是什么?
Apache Commons Daemon 可以将你的Java程序作为Linux守护进程或WinNT服务运行。
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(以免杀死仅重新使用已死亡的Java守护程序实例的PID的进程),然后杀死该进程。
当调用时,我的main()方法将首先在System.getProperty("pidfile")中定义的文件中写入其PID。
但是,有一个主要障碍:在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());
}
nohup
是一个非常糟糕的想法。 - symcbean我经常编写类似下面这样的脚本或命令行,如果我想要:
享受吧。
nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
我更喜欢使用nohup命令。这篇博客文章中提到了更好的方法,但我认为它们并没有更好到足以改变我的选择。
在Ubuntu上,我更喜欢使用libslack的“daemon”实用程序。这也是Jenkins在Ubuntu上使用的方式(这就是我得到这个想法的地方)。我已经将其用于基于Jetty的服务器应用程序,并且它运行良好。
当您停止daemon进程时,它会向JVM发出关闭信号。您可以通过使用Runtime.addShutdownHook()注册一个关闭钩子,在此时执行关闭/清理代码。
这要看情况。如果只是一次性的事情,我想将其守护进程化然后回家,但通常我会等待结果,可能会执行以下操作:
nohup java com.me.MyProgram &
在命令行下面,要清除它,你有很多选项。你可以监听SIGKILL,或者监听一个端口,在建立连接时关闭,定期检查一个文件。不同的方法有不同的弱点。如果用于生产环境,我会认真考虑,并将脚本放入/etc/init.d中,以nohup方式运行,并采用像tomcat一样更复杂的关机方式。
从https://cr.yp.to/daemontools/install.html安装daemon工具,按照说明进行操作,如遇问题,请尝试使用https://gist.github.com/rizkyabdilah/8516303中的说明。
在/etc/init/svscan.conf创建一个文件,并添加以下几行(仅适用于cent-os-6.7)
在 /service/vm/ 文件夹内创建一个名为 run 的新脚本,并添加以下内容。start on runlevel [12345] stop on runlevel [^12345] respawn exec /command/svscanboot
#!/bin/bash
echo starting VM
exec java -jar
/root/learning-/daemon-java/vm.jar
注意:
用您自己的Jar文件替换此处的Jar文件,或者替换任何Java类文件。请看这里:
http://jnicookbook.owsiak.org/recipe-no-022/
这是一个基于JNI的示例代码。在这种情况下,您将Java启动的代码守护化,并在C中执行主循环。但也可以将主要的守护服务循环放在Java中。
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo029
尽情享受JNI的乐趣吧!
nohup java prog &
。 - ceving