我有一个 Java 程序,我想在 linux 系统上进行守护进程。换句话说,我想在 shell 中开始运行它,并在我注销后让它继续运行。我也希望能够干净地停止程序。
我发现这篇文章结合使用了 shell 脚本和 Java 代码来解决问题。它看起来不错,但如果可能的话,我想要更简单的东西。
在 Linux 系统上守护 Java 程序的首选方法是什么?
Apache Commons Daemon会将您的 Java 程序作为 Linux 守护程序或 WinNT 服务运行。
如果你不能依赖其他地方引用的Java Service Wrapper(例如,如果你在 Ubuntu 上运行,它没有 SW 的打包版本),你可能想用老式的方式来做:让你的程序在 / 中写入它的 PID var/run/$progname.pid,然后围绕它编写一个标准的 SysV 初始化脚本(例如使用 ntpd 的脚本,它很简单)。最好也使其符合 LSB。
本质上,启动函数测试程序是否已经在运行(通过测试 /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
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());
}
我经常发现自己编写的脚本或命令行基本上看起来像这样,如果我想:
享受。
nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
我更喜欢nohup命令。博客文章说有更好的方法,但我认为它们还不够好。
你可以试试Java Service Wrapper,社区版是免费的,可以满足你的需求。
那要看。如果这只是一次性的事情,我想将其守护,然后回家,但通常我等待结果,我可能会这样做:
nohup java com.me.MyProgram &
在命令行。要彻底杀死它,您有很多选择。您可能有一个 SIGKILL 侦听器,或者侦听端口并在建立连接时关闭,定期检查文件。不同的方法有不同的弱点。如果它用于生产,我会多加考虑,并且可能会在 /etc/init.d 中添加一个脚本来阻止它,并进行更复杂的关闭,例如 tomcat 所具有的。
我在 Ubuntu 上的首选方式是使用 libslack 'daemon' 实用程序。这就是 Jenkins 在 Ubuntu 上使用的(这就是我产生这个想法的地方。)我已经将它用于基于 Jetty 的服务器应用程序,它运行良好。
当您停止守护进程时,它将向 JVM 发出关闭信号。此时,您可以通过使用 Runtime.addShutdownHook() 注册关闭挂钩来执行关闭/清理代码。
这个问题是关于守护任意程序(不是特定于 java 的),所以一些答案可能适用于您的案例:
DaemonTools :- 在 UNIX 上管理服务的更简洁的方法https://cr.yp.to/daemontools.html
从 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
#!/bin/bash echo starting VM exec java -jar /root/learning-/daemon-java/vm.jar
注意:将 Jar 替换为您自己的 Jar 文件。或任何 java 类文件。
重新启动系统
svstat /service/vm 现在应该已经启动并运行了!
看看这里:
http://jnicookbook.owsiak.org/recipe-no-022/
获取基于 JNI 的示例代码。在这种情况下,您将对作为 Java 启动的代码进行守护,并在 C 中执行主循环。但也可以将主、守护、服务循环放在 Java 中。
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo029
JNI 玩得开心!
nohup java -jar {{your-jar.jar}} > /dev/null &
这可能会奏效。