尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Tomcat开机自启动配置指南:systemd/init.d/rc.local全解析

发布时间:2026/9/26 6:48:04

资讯中心
01
ARTICLE

Tomcat开机自启动配置指南:systemd/init.d/rc.local全解析

Tomcat开机自启动配置指南:systemd/init.d/rc.local全解析
每次机房断电或者云服务器强制重启之后第一件事就是去敲/opt/tomcat/bin/startup.sh。如果忘了线上接口全部超时业务方几分钟之内就会找上门。这种体验做过线上部署的人应该都不陌生。这篇文章讲的就是怎么把 Tomcat 设置成开机自动启动让服务器一开机 Tomcat 自己就老老实实地跑起来省掉每次手动拉起的步骤。这套内容适合谁刚上手 Linux 部署的开发者、需要维护测试环境的后端同学、还有给产品部署做收尾的运维朋友。我会覆盖主流的 systemd 方案顺便把老系统的 init.d、应急用的 rc.local 也讲清楚保证你在 CentOS 7/8/9、Ubuntu 18.04 之后的版本上都能照着做。文章里的配置和坑都是实际服务器上反复验证过的。1. 先搞清楚为什么推荐用 systemd 而不是老方法很多人的第一反应是改/etc/rc.local或者在crontab里写reboot甚至还有人把startup.sh的路径直接塞进/etc/profile。这些做法不是完全不能用但都算不上正规的“服务管理”出了问题排查起来非常被动。现代 Linux 发行版的默认初始化系统基本都换成了 systemd直接拿它来管理 Tomcat 是成本最低、收益最高的路子。1.1 三种自启动方案的差异对比我先摆出几个方案的对比你看完就明白为什么主推 systemd方案适用系统是否支持失败重启服务状态跟踪日志管理systemd 服务CentOS 7/Ubuntu 16.04/Debian 8支持可配置完整可查 active/status统一 journalctl持久化init.d 脚本CentOS 6 及更老系统基本不支持仅能 start/stop/restart自己处理日志比较麻烦rc.local几乎全部版本不支持无进程死没死完全不可见无用 systemd 之后你可以通过systemctl status tomcat看到服务到底有没有起来可以设置Restarton-failure让进程异常退出后自动拉起还能用journalctl -u tomcat直接看启动日志。这三个能力几乎是运维排障的底线需求。rc.local 和 crontab 都做不到进程挂了就是挂了你只能自己事后发现。其实还有一层更隐蔽的好处systemd 对服务的启动顺序有依赖管理。Tomcat 依赖网络你在 Unit 段写上Afternetwork.target系统会等网络就绪后再启动 Tomcat。如果直接用 rc.local脚本执行的时候网络栈可能还没准备好Tomcat 在启动过程中碰一下网络接口就报错你又得多等一轮重启去碰运气。1.2 动手前先把这些信息确认好写配置之前先在服务器上确认四件事系统版本、JDK 路径、Tomcat 安装路径、运行用户。别到配置写到一半才发现路径写错。# 确认系统版本和 init 系统 cat /etc/os-release ps -p 1 -o comm # 确认 JDK 路径 java -version which java echo $JAVA_HOME # 确认 Tomcat 路径下面命令按自己实际安装目录来 ls /opt/tomcat/bin/catalina.sh结合我自己的经验Tomcat 一般放在/opt/tomcat或/usr/local/tomcatJDK 常见路径包括/usr/lib/jvm/java-1.8.0-openjdk、/usr/lib/jvm/java-11-openjdk-amd64或者你自己解压的/usr/local/jdk。下面所有配置我都会用具体路径做示例你直接替换成自己的路径就行。运行用户这一项我强烈建议单独建一个tomcat用户别直接用 root。生产环境里 Tomcat 通过 root 启动的坏习惯碰到一次被提权就够你喝一壶。useradd -r -s /bin/false tomcat chown -R tomcat:tomcat /opt/tomcat注意chown不只是处理 Tomcat 安装目录本身日志目录、临时文件目录、webapps 下可能被写入的文件都要一并有权限。第一次跑的时候用tomcat用户手动启动一次能及时发现权限问题而不是等开机自启之后才失败。2. 写一个可以完整控制的 tomcat.service这是全文的核心也是你在实际操作中最常遇到的场景。现在主流发行版都跑 systemd所以请把这套配置放稳它能满足日常 90% 的需求。2.1 一份可直接落地的 service 配置在/etc/systemd/system/下新建tomcat.service文件写入下面的内容[Unit] DescriptionApache Tomcat Web Application Container Afternetwork.target Wantsnetwork.target [Service] Typeforking Usertomcat Grouptomcat EnvironmentJAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk EnvironmentCATALINA_HOME/opt/tomcat EnvironmentCATALINA_BASE/opt/tomcat EnvironmentCATALINA_PID/opt/tomcat/tomcat.pid PIDFile/opt/tomcat/tomcat.pid ExecStart/opt/tomcat/bin/startup.sh ExecStop/opt/tomcat/bin/shutdown.sh ExecReload/bin/kill -s HUP $MAINPID TimeoutStartSec300 TimeoutStopSec30 Restarton-failure RestartSec5 [Install] WantedBymulti-user.target逐段解释一下。[Unit]段里Description只是描述After和Wants表示这个服务在网络服务启动后再启动。After管的是顺序Wants管的是依赖组合起来逻辑比较完整。[Install]段是给enable命令用的multi-user.target代表系统进入多用户模式后自动拉起这基本涵盖了大部分服务器的常规运行状态。重点看[Service]段Typeforking是 Tomcat 这类脚本式启动服务的通用配置。startup.sh执行后会先 fork 出一个子进程继续跑 JVM父进程随即退出systemd 通过 PID 文件追踪真正的 Tomcat 主进程。Environment字段专门解决 systemd 环境变量干净的问题后面我要讲这是最容易踩坑的地方之一。2.2 这段配置里最容易踩的3个坑第一个坑PID 文件根本不存在。很多人照抄网上配置写了PIDFile/opt/tomcat/tomcat.pid结果 Tomcat 的catalina.sh脚本默认根本不会生成这个 PID 文件只有设置了CATALINA_PID环境变量才生成。光在 service 文件里写EnvironmentCATALINA_PID...还不行因为/opt/tomcat/bin/startup.sh是属于 Tomcat 的脚本它会加载自己的setenv.sh和catalina.sh不认 systemd 给它塞的环境变量。正确做法是创建setenv.shcat /opt/tomcat/bin/setenv.sh EOF #!/bin/bash CATALINA_PID$CATALINA_BASE/tomcat.pid JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk EOF chmod x /opt/tomcat/bin/setenv.shcatalina.sh启动时如果发现同目录下有setenv.sh会自动 source 它。这样 PID 文件路径和 JAVA_HOME 配置就双保险了。你在调试阶段可以手动执行一次/opt/tomcat/bin/startup.sh确认ls /opt/tomcat/tomcat.pid能看到文件再做后续的 systemd 配置。第二个坑Type 类型设置错误。如果你图省事把ExecStart/opt/tomcat/bin/catalina.sh start配成Typesimplesystemd 会认为启动命令一结束服务就算停了然后开始执行一系列停止逻辑导致进程刚起来就被干死。反过来如果用了Typeforking但 PID 文件路径对不上systemctl status tomcat就会一直显示activating (start)卡在那里不动。这里我给一个更稳妥的替代写法直接用catalina.sh run前台运行模式Typesimple ExecStart/opt/tomcat/bin/catalina.sh run这种方式不需要关心 PID 文件systemd 直接把 JVM 进程当主进程跟踪ExecStop也省了因为 systemd 停服务时会直接终止主进程。如果你不想折腾 PID 文件这个环节就优先用这个方案省心很多。第三个坑环境变量配置不生效。登录终端的时候JAVA_HOME通常来自/etc/profile或用户自己的.bashrc但 systemd 启动服务时不会加载这些文件。结果就是你手动执行/opt/tomcat/bin/startup.sh一切正常换成 systemd 启动就报Cannot find /usr/bin/java。解决办法就是我们在 service 文件里显式声明Environment或者依赖前面写的setenv.sh。我一般两手一起上service 文件里写一份setenv.sh里再写一份保证无论从哪个入口拉起都不缺环境变量。2.3 让配置真正生效的4条命令写完 service 文件之后执行下面四条命令# 1. 让 systemd 重新加载配置 systemctl daemon-reload # 2. 设置开机自启 systemctl enable tomcat # 3. 立即启动服务 systemctl start tomcat # 4. 查看状态 systemctl status tomcat这里有个很容易漏掉的动作改了 service 文件之后必须先执行systemctl daemon-reload否则 systemd 用的还是旧配置。enable只是在/etc/systemd/system/multi-user.target.wants/下创建一个符号链接表示开机启动这个服务它不会自动加载新配置。我见过不少同事直接改完文件就systemctl restart tomcat结果发现配置完全没变白忙活半天。启动之后systemctl status tomcat的输出里会显示Active: active (running)并且能看到主进程的 PID。如果显示loaded状态正常但active是dead按第 4 部分的排查流程走一遍就能定位。这个环节是处理系统启动故障前的最后一道防线务必确认状态是 running 再往下继续。3. 不依赖 systemd 的兼容方案也要会虽然 systemd 是大势所趋但你保不齐会遇到老版本的 CentOS 6、某些精简的容器宿主机或者遇到 systemd 服务文件无论如何都起不来的边缘场景。多会两手方案心里不慌。3.1 老系统的 init.d 脚本方案CentOS 6 及更早版本默认使用 SysVinit服务脚本放在/etc/init.d/下。写一个 Tomcat 的启动脚本核心就是通过chkconfig来控制开机启动。参考脚本如下#!/bin/bash # chkconfig: 2345 90 10 # description: Apache Tomcat CATALINA_HOME/opt/tomcat export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk case $1 in start) echo Starting Tomcat... $CATALINA_HOME/bin/startup.sh ;; stop) echo Stopping Tomcat... $CATALINA_HOME/bin/shutdown.sh ;; restart) echo Restarting Tomcat... $CATALINA_HOME/bin/shutdown.sh sleep 3 $CATALINA_HOME/bin/startup.sh ;; status) ps -ef | grep catalina | grep -v grep ;; *) echo Usage: $0 {start|stop|restart|status} exit 1 esac exit 0第二行的# chkconfig: 2345 90 10不是注释它是给chkconfig工具读的元数据格式是“运行级别 启动优先级 关闭优先级”。2345 表示在这几个运行级别开启90 和 10 是服务的启停顺序。写完后执行chmod x /etc/init.d/tomcat chkconfig --add tomcat chkconfig tomcat on这种方案的缺点很明显进程挂了没人管日志靠 Tomcat 自己写文件开机顺序完全依赖优先级数字改动起来很脆。所以现在真的不建议在新系统上折腾它遇到老系统顺手维护一下就好。3.2 应急场景下的 rc.local 方案有一种情况很尴尬sysadmin 不允许往服务器里加 systemd service 文件或者某些虚拟化模板把 systemd 阉割过。这时候rc.local是最快的应急出口。先把rc.local让它能被执行# 部分系统该文件默认没有执行权限 chmod x /etc/rc.d/rc.local # 编辑文件在末尾追加启动命令 vi /etc/rc.d/rc.local # 添加以下内容 /opt/tomcat/bin/startup.shsystemd 系统上/etc/rc.local和/etc/rc.d/rc.local是同一个文件但rc-local.service默认只在文件具备执行权限时才生效。这个细节非常容易踩你明明往文件里写了启动命令重启后就是没执行因为没加执行权限。另外rc.local 里的命令是顺序执行的如果 Tomcat 这条命令卡住了后面的命令全部阻塞。我一般会在后台执行并写日志避免启动过程互相拖累nohup /opt/tomcat/bin/startup.sh /var/log/tomcat-rc.log 21 应急归应急用 rc.local 管理服务有个致命问题没有任何探活机制Tomcat 中途崩了不会有人帮你拉起来。所以它适合临时救火不适合作为长期方案稳定环境别偷懒。3.3 一台机器多个 Tomcat 实例怎么处理一台服务器上跑两三个 Tomcat 实例仍然是常见的比如一套 eureka 集群部署在同一台机器上。这时候不要用单个 service 文件试图管理多个实例要每个实例一套独立配置思路是按CATALINA_BASE区分。假设有两个实例/opt/tomcat-instance1和/opt/tomcat-instance2它们各自的server.xml设置不同的 HTTP 端口、AJP 端口和 shutdown 端口。然后分别创建两个 systemd 服务文件# tomcat1.service 和 tomcat2.service 的区别仅在于 Environment 和路径字段 EnvironmentCATALINA_BASE/opt/tomcat-instance1 EnvironmentCATALINA_HOME/opt/tomcat-instance1 ExecStart/opt/tomcat-instance1/bin/startup.sh这里我建议两个实例都用/opt下独立的完整目录而不是共享CATALINA_HOME只区分CATALINA_BASE。共享二进制虽然省空间但升级或配置修改时容易互相影响排查问题的难度也翻倍。实战中发现区分开之后每个实例的日志、PID 文件都各自独立journalctl -u tomcat1和journalctl -u tomcat2分开看问题定位快很多。4. 重启后验证与常见故障排查配置完成不等于万事大吉。我见过太多人systemctl enable tomcat之后就撒手不管下次服务器重启才发现 Tomcat 没起来而且日志里写满了看不懂的错误。设置开机自启后的第一件事就是手动重启一次照着下面的清单做验证。4.1 重启后的验证清单# 重启服务器这一步会断开 SSH注意提前保存现场 reboot # 重新登录后检查 Tomcat 服务状态 systemctl status tomcat # 检查 8080 端口是否监听 ss -lntp | grep 8080 # 用 curl 验证本地 HTTP 响应 curl -I http://localhost:8080不要只看systemctl status显示 active 就完事很多情况是服务起来了但业务没法访问。检查端口监听和 HTTP 响应更接近真实可用状态。curl -I能看到返回的 HTTP 头如果 Tomcat 正常一般返回HTTP/1.1 200或302具体看你部署的应用路径。我用这套清单排查过无数次问题简单粗暴但非常可靠。4.2 服务起不来的高频原因我按实际遇到概率排个序列成速查表你照着对号入座现象可能原因处理方式systemctl status显示 failed日志提示 java 命令找不到JAVA_HOME 未传入service 里写 Environment或 setenv.sh 再声明一遍端口明明被监听但curl超时SELinux 拦截或者防火墙未放行查看 SELinux 状态放行 8080 端口启动后进程立刻消失状态变成 deadType 类型不对或者 PID 文件指向错误改用catalina.sh runTypesimple状态一直activating (start)超时报错PID 文件没有真正生成手动跑 startup.sh确认 tomcat.pid 出现业务能看到但重启后偶尔起不来Afternetwork.target不够网络恢复时机晚增加Wantsnetwork-online.target并安装网络等待服务SELinux 这个问题在 CentOS 和 RHEL 系列上特别明显。你会在日志里看到avc denied的提示但没有明显报错信息只是端口起不来或者访问被拒。最简单的验证方式是临时关闭 SELinux 试试如果恢复正常再考虑写针对性的 SElinux 策略当前先用setsebool -P httpd_can_network_connect 1放行即可。数据比较复杂的场景再细化策略别一上来就setenforce 0长期关闭。4.3 看日志的正确姿势Tomcat 的日志分两层第一层是 systemd 统一收集的第二层是 Tomcat 自己的文件日志。排查的时候两边的日志都要看因为有些错误只会在某一侧出现。# 实时跟踪 systemd 视角的 Tomcat 日志 journalctl -u tomcat -f # 看最近 100 行适合启动失败后回查 journalctl -u tomcat -n 100 # 按时间过滤 journalctl -u tomcat --since 10 minutes ago # 看 Tomcat 自己的启动日志 tail -n 200 /opt/tomcat/logs/catalina.out我自己的习惯是如果journalctl里没有明显线索就立刻去翻catalina.out特别是启动阶段Tomcat 会详细打印 JVM 参数、加载了哪些配置、有没有端口冲突。catalina.out里如果能翻到SEVERE级别的异常往往就是问题根因比 systemd 日志里的泛泛错误有用得多。还有一个绕不过去的经典问题Tomcat 乱码。启动日志里中文路径或中文注释出现乱码一般不影响启动但如果你需要拿日志做分析就非常烦。排查时可以顺手在setenv.sh里加上export JAVA_OPTS$JAVA_OPTS -Dfile.encodingUTF-8 -Dsun.jnu.encodingUTF-8这个不做强制要求但线上日志可读性会提升很多尤其是要接入日志平台的情况。5. 写在最后的一点运维体会配置开机自启这件事技术本身不难难的是考虑全各种边界情况。这几套方案我前前后后在几十台服务器上用过从 CentOS 6 时期的 init.d 脚本到后来全面转向 systemd中间踩过的坑基本都写在上面了。有一点我想单独强调尽量别在 service 文件里配置Restartalways永远不要小看一个出 bug 的 Java 进程在崩溃重启循环里对服务器 CPU 的消耗。用Restarton-failure配合RestartSec5既能保证进程意外退出时自动拉起又不会出现几秒钟重启一次的疯狂循环。另外每次改完 Tomcat 的配置文件或 service 文件有条件的话直接重启一次服务器验证别等到下次真的断电了才在半夜发现问题。把验证环节推到配置时是运维性价比最高的习惯。这套配置整好之后后续你再去接 Jenkins 自动部署、做端口映射都会顺很多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。