当前位置:首页 > 探索

tomcat做成服务

把 Tomcat 做成系统服务,做成最直接的服务好处是开机自启、崩溃后自动拉起、做成日志统一走系统日志。服务但很多人第一次配完 systemd 单元文件,做成重启后 Tomcat 起不来,服务一查日志全是做成权限问题——十有八九是没搞清 Tomcat 到底以哪个用户身份在跑。

我见过一个案例:运维在 CentOS 7 上装完 Tomcat 9,服务手写了一个 tomcat.service,做成User=tomcat,服务Group=tomcat,做成看着没问题。服务结果启动时报 java.io.FileNotFoundException: /opt/tomcat/logs/catalina.out (Permission denied)。做成原因很简单,服务/opt/tomcat 整个目录是做成 root 解压的,logs 子目录属主是 root,tomcat 用户根本没写权限。chown -R tomcat:tomcat /opt/tomcat 之后立刻正常。

所以第一步不是急着写 unit 文件,先确认三件事:JDK 路径、Tomcat 安装目录、运行用户。用 which java 拿到真实路径,别信 JAVA_HOME 环境变量,systemd 不读你的 .bashrc。

下面是一个能直接用的模板,放在 /etc/systemd/system/tomcat.service:

[Unit] Description=Apache Tomcat 9 After=network.target [Service] Type=forking User=tomcat Group=tomcat Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk" Environment="CATALINA_HOME=/opt/tomcat" Environment="CATALINA_BASE=/opt/tomcat" Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid" ExecStart=/opt/tomcat/bin/startup.sh ExecStop=/opt/tomcat/bin/shutdown.sh Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target 

几个坑点值得单独说。第一,Type=forking 必须配 PIDFile 或者 CATALINA_PID,否则 systemd 不知道主进程是谁,stop 的时候会卡住。第二,Restart=on-failure 比 always 更合理,手动 stop 后不应该被拉起来。第三,startup.sh 和 shutdown.sh 本质是 shell 脚本,依赖 CATALINA_HOME,环境变量必须显式声明。

配完执行 systemctl daemon-reload,然后 systemctl enable tomcat 和 systemctl start tomcat。看状态用 systemctl status tomcat -l,-l 参数能显示完整日志,不然会被截断。如果失败,journalctl -u tomcat -n 50 --no-pager 直接看最后 50 行。

有个细节容易被忽略:Tomcat 的 logs 目录下 catalina.out 默认会无限增长。做成服务后,systemd 的 journal 只管 stdout,管不了这个文件。我的做法是在 logrotate 里加一条配置,或者干脆把 catalina.out 重定向到 /dev/null,让日志走 logging.properties 里的文件 handler。后者更干净,但需要改 Tomcat 配置,看个人取舍。

另外,如果你的 Tomcat 跑在 1024 以下端口,比如 80,必须给 java 二进制加 cap_net_bind_service 能力,或者用 authbind。直接 User=tomcat 是绑不上的,报 Permission denied。命令是 setcap 'cap_net_bind_service=+ep' /usr/lib/jvm/java-11-openjdk/bin/java,但每次 JDK 升级后要重新执行。

Windows 环境下更简单,bin 目录下自带 service.bat,service.bat install Tomcat9 就完事。但要注意,它默认用 Local System 账户跑,权限过大。改成专用用户需要在服务属性里手动配登录身份,而且该用户要有 Log on as a service 权限。

说到底,Tomcat 做服务本身不复杂,复杂的是环境差异。同一份 unit 文件,在 Ubuntu 和 CentOS 上可能因为 SELinux 或 AppArmor 表现完全不同。遇到问题先看 journalctl,再看 Tomcat 自己的 catalina.out,最后查系统审计日志,顺序别搞反。

分享到: