在 Centos 7 上使用 systemd 启动 Tomcat 8.5

在 Centos 7 上使用 systemd 启动 Tomcat 8.5

我安装了 Tomcat 8.5 并且能够手动成功启动它,例如:

su tomcat startup.sh

工作正常并且 tomcat 能够在端口 8080 上提供服务。

我需要自动启动,所以我创建了文件 /etc/systemd/system/tomcat-prod.service:

[Unit]
Description=Tomcat 8.5 servlet container - Production
After=network.target

[Service]
Type=forking

ExecStart=/opt/appservers/production/apache-tomcat-8.5.37/bin/startup.sh
ExecStop=/opt/appservers/production/apache-tomcat-8.5.37/bin/shutdown.sh

User=tomcat
Group=tomcat   

[Install]
WantedBy=multi-user.target

该文件故意是空的,我的所有环境变量都在 setenv.sh 中。我尝试使用以下命令运行它:

# systemctl daemon-reload
# systemctl start tomcat-prod

由于某种原因,上述情况导致 Tomcat 在启动后立即退出。我没有收到任何日志来解释原因。Tomcat 在启动时会创建一个空的 catalina.out 文件,systemctl status tomcat-prod 仅提供以下内容:

tomcat-prod.service-Tomcat 8.5 servlet 容器-生产已加载:已加载(/etc/systemd/system/tomcat-prod.service;已启用;供应商预设:已禁用)活动:失败(结果:退出代码)自 2019-01-04 星期五 08:08:27 UTC 起;3 秒前进程:3583 ExecStop=/opt/appservers/production/apache-tomcat-8.5.37/shutdown.sh(代码=exited,状态=203/EXEC)进程:3569 ExecStart=/opt/appservers/production/apache-tomcat-8.5.37/bin/startup.sh(代码=exited,状态=0/SUCCESS)主 PID:3581(代码=exited,状态=0/SUCCESS)

1 月 4 日 08:08:27 *.net startup.sh[3569]: 启动时发现现有 PID 文件。1 月 4 日 08:08:27 *.net startup.sh[3569]: 正在删除/清除过时的 PID 文件。

有人能给我指明正确的方向吗?

答案1

Systemd 会跟踪每个服务的“主进程”,以便准确了解服务是否仍然处于活动状态。当主进程退出时,服务管理器会假定服务已崩溃或自行停止。当服务停止时,其所有剩余进程都会自动终止,为将来的启动提供干净的状态。

为了类型=分叉服务,确定哪个是“主”进程可能有些困难,尤其是当它隐藏在层层 shell 脚本后面时。systemd 中的默认启发式方法对于常规守护进程很有效,但在你的情况下,它们可能会误认为其中一个 shellscript 层是主进程,而不是 tomcat 本身。因此,一旦脚本结束后,该服务被认为已经停止,并且它的残余(包括真正的守护进程)也被杀死。

您有两个选择:

  • 使用“pidfile”明确指定主进程。这是 SysVinit 使用的传统方法。您的启动脚本已将 Tomcat 守护进程的进程 ID 存储在某个文件中,因此您的 tomcat.service 单元需要使用该PIDFile=选项引用它。这样,服务管理器就不需要自动检测启发式方法,只需跟踪提供的 PID 作为主进程。

  • 完全摆脱 shellscripts 并直接从启动 Tomcat执行开始=选项。这是 systemd 的推荐方法,您可以找到各种发行版的打包程序已经编写的示例 .service 单元。例如,Arch Linux(带有 Jsvc 的 Tomcat 8)

答案2

毫无疑问,granity 已经意识到了systemd 恐怖其他地方提到,作者写道“我们已经有一个更好的守护进程管理器。它是 systemd”——这意味着我们也不需要 jsvc。然而,在该页面上,作者确实添加了一个“奖励曲目”:“请注意,M. Benjamin 使用 run 而不是 start 来调用 catalina.sh。对于旨在运行守护进程而不是生成守护进程的系统,实际上还有另一条通过 catalina.sh 的路径。”对 Jonathan de Boyne Pollard 的脚本进行一些调整后,我得到了以下内容A)不太难写,b)似乎消除了功能中不必要的层次、不必要的 PID 的使用以及额外的守护进程命令,C) 的输出很明确:

# file: /usr/local/lib/systemd/system/tomcat.service

[Unit]
Description=Apache Tomcat 9
After=network.target

[Service]
User=tomcat
Group=tomcat

ExecStart=/opt/apache/tomcat/bin/catalina.sh run
Type=simple

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=0

# SIGTERM signal is used to stop the Java process
KillSignal=SIGTERM

# Java process is never killed
SendSIGKILL=no

# When a JVM receives a SIGTERM signal it exits with code 143
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

有关其他选项,请参阅 catalina.sh 脚本的顶部,其中内容如下:

#   Do not set the variables in this script. Instead put them into a script
#   setenv.sh in CATALINA_BASE/bin to keep your customizations separate.

相关内容