我们可以将 pid 写入存储在 systemd 中的文件中吗?

我们可以将 pid 写入存储在 systemd 中的文件中吗?

我有一个在启动时启动 java 应用程序的脚本。

[Unit]
Description=test Background

[Service]
ExecStart=/bin/bash -c "/usr/bin/java -jar /var/www/tset.com/*.jar"
Type=simple
WorkingDirectory=/var/www/test.com

[Install]
WantedBy=multi-user.target

我们可以编辑它以将 pid 写入特定位置的文件中吗?

举个例子,

ExecStart=/bin/bash -c "/usr/bin/java -jar /var/www/test.com/*.jar | echo $! > ${RUNNING_PID}"

答案1

您应该能够直接运行 java,而不是运行运行 java 的 bash shell。如果这样做,您可以运行systemctl 显示获取 PID 的命令

systemctl show -p MainPID <your service name>

当然假设你的 java 应用程序不会创建更多进程。

如果你的服务名称文件以 .service 结尾,那么你可以省略 .service 后缀<your service name>

如果您通过 bash 脚本运行,那么您将获得运行 java 进程的 bash shell 的 pid。

答案2

我解决这个问题的方法是这样的:

ExecStart=/bin/bash -c 'echo $$ > /var/run/tset.pid; exec /usr/bin/java -jar /var/www/tset.com/*.jar'

有几件事需要注意:

  • 你要做的是写入.pid包含进程 PID 的文件,在 Linux 上“事实上的”位置就是把它放进/var/run

  • 操作>符用于重定向stdout,其将是或 shell PIDecho的内容。$$

  • 为什么是 shell PID ?因为我们接下来要使用的exec命令是将取代shell进程与您的 Java 应用程序。 PID 1234 代表 shell,现在将代表 Java 应用程序的 PID 1234。

这种方法虽然看起来很复杂,但实际上更为合适:

  • 我们知道 PID,而不需要使用pspgrep查找它,我们不必应用复杂的解析,如果应用程序的多个实例已经在运行,我们也不会遇到问题(如果您使用 systemd 服务来启动它,则不应该出现这种情况,但考虑到这种可能性也没有坏处)
  • 并且exec不会因为启动多个进程而浪费资源。当您有类似bash -c '/usr/bin/java -jar myapp.jar & pgrep -f myapp.jar > /var/run/myapp.pid '3 个进程的情况时。在上面建议的命令中 - 我们用一个进程替换另一个进程。

当然,这只是一个例子。根据您的情况调整必要的程度,/var/run/tset.pid这里选择它只是作为一个例子 - 命名和文件位置由您决定,但我建议使用它/var/run以与其他应用程序保持一致。

边注:

| echo $! > ${RUNNING_PID}"部分至少由于一个原因而不合适:${RUNNING_PID}是一个变量,但是它没有在任何地方声明,因此它将被 shell 中的 plank 替换。是|毫无意义的 - stdoutjava 应用程序连接到stdin其中echo在您希望将应用程序的输出发送到另一个应用程序的情况下是合适的,但 echo 不会读取stdin- 即在这里它是毫无意义的。

当然,如果应用程序本身(即 java 应用程序)fork - 即创建 - 另一个进程,那么这$$不会有太大帮助,但公平地说,如果应用程序确实创建了多个fork,那么创建和管理文件并报告主进程 pid 应该是应用程序本身的工作.pid

答案3

systemd 将你的进程的 pid 留在环境中,因此你可以在脚本中使用它:

    [Unit]

    [Service]
    ExecStart=/home/blah/my-process.sh
    ExecStop=/bin/kill -HUP $MAINPID
    PIDFile=/home/blah/blah.pid

    [Install]

相关内容