如何将 Java 程序妖魔化?

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

我发现 这篇文章使用了 shell 脚本和 Java 代码的组合来完成这个任务。看起来不错,但如果可能的话,我想要简单一点的。

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

103736 次浏览

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

您可以尝试 Java 服务包装器,社区版是免费的,并满足您的需要。

我更喜欢 没有命令。博客上说有更好的方法,但我不认为它们足够好。

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

nohup java com.me.MyProgram &

在命令行上。要干净利落地杀死它,你有很多选择。您可能有一个 SIGKILL 的侦听器,或者在建立连接时侦听端口并关闭,定期检查一个文件。不同的方法有不同的弱点。如果是在生产环境中使用,我会更多地考虑它,可能会在/etc/init.d 中添加一个脚本,这样就不会停止它,并且会进行更复杂的关闭,比如 tomcat 所具有的关闭。

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

  1. 运行一个对吸烟免疫的程序
  2. 它与产生它的 shell 完全断开连接,并且
  3. 从 stderr 和 stdout 生成一个日志文件,其中的内容也将显示,但
  4. 允许我停止查看正在进行的日志,并在不中断正在运行的进程的情况下做其他事情

好好享受吧。

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

如果你不能依赖 Java 服务包装器引用的 其他地方(例如,如果你在 Ubuntu 上运行,它没有软件包版本) ,你可能想要用老式的方法: 让你的程序在/var/run/$proname.PID 中编写它的 PID,然后围绕它编写一个标准的 SysV init 脚本(例如 ntpd 的那个脚本,它很简单)。最好还要兼容 LSB。

本质上,start 函数测试程序是否已经在运行(通过测试/var/run/$procname.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/$proname.PID,测试该文件是否是正在运行的进程的 PID,验证它是否是 Java VM (这样就不会杀死一个只是从 Java 守护进程的死实例中重用了 PID 的进程) ,然后杀死该进程。

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

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

我在 Ubuntu 上的首选方法是使用 libslash‘ daemon’实用程序。这是 Jenkins 在 Ubuntu 上使用的(这也是我的想法)我在基于 Jetty 的服务器应用程序中使用过它,它工作得很好。

当您停止守护进程时,它将发出关闭 JVM 的信号。您可以通过使用 Runtime.addShutdownHook ()注册一个关闭钩子来执行关闭/清理代码。

DaemonTools:-在 UNIXhttps://cr.yp.to/daemontools.html上管理服务的更清晰的方法

  1. 从 url < a href = “ https://cr.yp.to/daemontools/Install.html”rel = “ nofollow”> 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
  1. 在/service/vm/文件夹中创建一个名为 快跑的新脚本,并添加以下代码行。
#!/bin/bash
echo starting VM
exec java -jar
/root/learning-/daemon-java/vm.jar

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

  1. 重启系统

  2. Svstat/service/vm 现在应该已经启动并运行了。

  3. Svc-d/service/vm 现在应该关闭 vm。
  4. Svc-u/service/vm 应该立即启动 vm。

看看这里:

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

获取基于 JNI 的示例代码。在这种情况下,您将以 Java 启动的代码守护化,并且在 C 中执行 main 循环。但是也可以将 main、 daemon、 service 循环放在 Java 中。

Https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeno029

祝你和 JNI 玩得开心!

nohup java -jar \{\{your-jar.jar}} > /dev/null &

这个可能有用。