如何告诉 systemd java 进程已退出但使用新的 pid 重新启动?

如何告诉 systemd java 进程已退出但使用新的 pid 重新启动?

我为 java 应用程序设置了 systemd 服务。一切工作正常,直到 java 应用程序自行重新启动。重新启动时,systemd 观察到的主 java 进程将以状态 0 退出并启动其自身的新实例。 Systemd 现在认为该进程已退出。

我怎样才能告诉systemd重新启动的java应用程序启动的进程的新PID?

我怎样才能获得新启动进程的PID?

systemd服务定义如下:

[Unit]
Description=MyJavaApp
After=network.target

[Service]
Type=simple
User=myuser
ExecStart=/usr/bin/java -jar -Djava.awt.headless=true /opt/MyJavaApp/MyJavaApp.jar &
ExecStop=/usr/bin/java -jar -Djava.awt.headless=true /opt/MyJavaApp/MyJavaApp.jar -quit

[Install]
WantedBy=multi-user.target

答案1

不幸的是你不能。通过type=simple,systemd 跟踪参数直接执行的进程ExecStart。尽管type=forking仍然存在类似的问题,但 systemd 会跟踪进程,一旦退出,systemd 就会认为它已经死了。

这样做的困难在于 systemd 无法知道这就是应用程序的正常行为。您的应用程序可能有一个主进程,然后生成子工作进程。因此 systemd 会认为你的主人已经死了,并且留下了一些需要清理的孩子。

有两种方法可以解决这个问题:

  1. 以某种方式创建一个 systemd 执行的监视进程,该进程将启动您的应用程序。然后以某种方式让这个监视进程能够区分应用程序退出与 fork 退出之间的区别。这可能相当难以实现,因为跟踪子进程的子进程并不容易。
    一种可行的方法是创建一个匿名管道,将管道的写入端传递给进程,并等待其读取端的 EOF。只要您的应用程序不关闭未知的文件描述符,它就应该可以工作。
  2. 更改您的应用程序以使用+exec代替。这样新进程使用与旧进程相同的PID。forkexec

相关内容