如何守护Java程序?
我有一个Java程序,我想在Linux系统上守护进程。 换句话说,我想开始在一个shell中运行它,并在退出后继续运行它。 我也希望能够干净地停止程序。
我发现这篇文章使用了shell脚本和Java代码的结合。 它看起来不错,但如果可能的话,我想要更简单一些。
在Linux系统上将Java程序进行守护程序的首选方法是什么?
Apache Commons Daemon将作为Linux守护进程或WinNT服务运行您的Java程序。
如果你不能依赖其他地方引用的Java Service Wrapper (例如,如果你在Ubuntu上运行,没有软件包的版本),那么你可能要用老式的方式来做:你的程序要把它的PID写入/ var / run / $ progname.pid,然后编写一个标准的SysV初始化脚本(例如使用ntpd作为例子,这很简单)。 最好也使其符合LSB。
实质上,启动函数testing程序是否已经运行(通过testing/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
停止函数检查/var/run/$progname.pid,testing该文件是否是正在运行的进程的PID,validation它是否为Java VM(以免杀死一个只是从死亡中重用PID的进程我的Java守护进程的实例),然后杀死这个进程。
当被调用时,我的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()); }
我经常发现自己编写的脚本或命令行本质上是这样的,如果我想:
- 运行一个不受嘘声影响的程序
- 这与产生它的shell是完全分离的
- 从stderr和stdout生成一个日志文件,其内容也被显示,但是
- 允许我停止查看正在进行的日志,并在不中断正在运行的过程的情况下执行其他操作
请享用。
nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
我更喜欢nohup命令。 博客文章说有更好的方法,但我认为他们不够好。
你可以尝试Java服务包装 ,社区版是免费的,并满足您的需求。
我在Ubuntu上的首选方式是使用libslack'守护进程'实用程序。 这就是Jenkins在Ubuntu上所使用的(这是我的想法)。我已经将它用于基于Jetty的服务器应用程序,并且运行良好。
当你停止守护进程时,它会发信号通知JVMclosures。 您可以通过使用Runtime.addShutdownHook()注册一个closures钩子来执行closures/清除代码。
那要看。 如果只是一次性的事情,我想把它变成现实,然后回家,但通常我会等待结果,我可能会这样做:
nohup java com.me.MyProgram &
在命令行。 要干净地杀死它,你有很多select。 您可能拥有SIGKILL的侦听器,或者在端口上侦听并在build立连接时closures,定期检查文件。 差异方法有不同的弱点。 如果是在生产环境中使用的话,我会考虑一下,可能会在/etc/init.d中引入一个脚本来解决这个问题,并且有一个更复杂的closures,比如tomcat的function。
这个问题是关于一个任意程序的守护进程(而不是java特定的),所以一些答案可能适用于你的情况:
DaemonTools:在UNIX上pipe理服务的一种更简洁的方法https://cr.yp.to/daemontools.html
-
从urlhttps://cr.yp.to/daemontools/install.html安装守护进程工具,按照那里提到的指示,对于任何问题,请尝试指示https://gist.github.com/rizkyabdilah/8516303
-
在/etc/init/svscan.conf创build一个文件并添加下面的行(只需要cent-os-6.7)
start on runlevel [12345] stop on runlevel [^12345] respawn exec /command/svscanboot
- 创build一个名为run inside / service / vm / folder的新脚本,并添加以下行。
#!/bin/bash echo starting VM exec java -jar /root/learning-/daemon-java/vm.jar
注意:用你自己的Jar文件replaceJar。 或任何Java类文件。
-
重新启动系统
-
svstat / service / vm应该已经启动并运行了!
- svc -d / service / vm现在应该把vm降下来!
- svc -u / service / vm现在应该带上vm了!
如果你喜欢新的东西,你可以试试Akuma 。 (小)信息也请参阅Kohsuke Kawaguchi的博客 。
看看这里:
http://jnicookbook.owsiak.org/recipe-no-022/
为基于JNI的示例代码。 在这种情况下,您将启动为Java的代码进行守护程序,并在C中执行主循环。但是,也可以将Java,守护进程的服务循环放入Java中。
https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029
与JNI玩得开心!