news 2026/9/9 4:27:09

Linux下Tomcat 8.5.35生产环境部署全流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux下Tomcat 8.5.35生产环境部署全流程实战

简介:Linux版Tomcat 8.5.35压缩包面向需要在Linux服务器上运行Java Web应用的开发与运维人员,封装了Catalina、Jasper、Coyote等核心组件,可直接解压用于部署Servlet/JSP项目,免去手动编译配置。资源共645个文件,约9.2MB,以HTML页面、Java/JSP源文件、class类文件为主,还包含sh启动脚本、jar依赖库、XML配置文件等,能够完整支撑从服务启停、连接器配置到应用发布的常见需求。压缩包目录结构清晰,bin、conf、lib、webapps、logs等关键目录随包提供,便于快速掌握各模块用途,也方便结合SSL配置、访问控制等开展二次安全加固。目前已有548人学习下载,适合作为本地测试或生产环境的轻量级部署基础,可直接将WAR包放入webapps完成热部署,帮助使用者减少环境搭建时间,聚焦业务代码开发。 拿到一个“Linux版本tomcat8-8.5.35.tar.gz”安装包,看起来就是一个再普通不过的压缩包,但真把它部署到生产环境时,很多人的第一反应是“解压、启动、完事”。实际上这里面的门道不少,从校验压缩包完整性、选JDK版本、配置JAVA_HOME,到调整内存参数、注册systemd服务,每一步都可能影响你后面几个月的运维体验。这篇文章我就从零开始,把Tomcat 8.5.35在Linux上的部署流程完整拆开,把我踩过的坑、验证过的方案、排查过的故障一并写清楚,希望对正在折腾这台服务器的你有点实际帮助。

1. 部署前的环境准备与软件包校验

1.1 这台机器到底适不适合跑Tomcat

动手解压之前,先确认操作系统环境。Tomcat本身是纯Java写的,理论上有JDK就能跑,但不同Linux发行版、不同内核版本带来的差异还是存在的。至少你要搞清楚三件事:

  • 系统是CentOS 7、CentOS 8、Ubuntu还是Debian,包管理器和防火墙操作方式完全不同;
  • 机器架构是x86_64还是ARM,这决定了你下载的JDK安装包是哪一份;
  • 系统内存、磁盘空间多大,Tomcat虽然轻量,但JVM启动默认就占几百MB内存,太小了跑不动。

我用uname -acat /etc/os-release确认过环境后,再看磁盘空间,df -h /opt确保至少预留2GB以上空间。很多人的Tomcat部署到后面出问题,最根本的原因就是一开始在不合适的系统上硬装,装完各种诡异故障,还以为是Tomcat的锅。

1.2 校验tar.gz完整性的两种方式

这一步是安全底线,可惜大多数人直接跳过了。拿到apache-tomcat-8.5.35.tar.gz之后,先别急着解压,花一分钟做完整性校验。官网会同时提供.sha512.asc两个校验文件,对应两种校验思路。

校验SHA512哈希,确认文件在下载过程中没有损坏或被篡改。命令很简单:

echo "从官网复制的sha512值 apache-tomcat-8.5.35.tar.gz" | sha512sum -c -

输出OK就说明文件没问题。如果提示FAILED,直接删掉重新下载,不要犹豫。

更高阶的校验方式是用GPG验证签名,确认这个包确实是Apache官方发布的。做法是先导入Apache Tomcat的官方公钥,再执行:

gpg --verify apache-tomcat-8.5.35.tar.gz.asc apache-tomcat-8.5.35.tar.gz

平时自己实验室里部署,校验SHA512基本够用了。生产环境建议两步都做,尤其是从镜像站下载的包,镜像同步出错的情况真的碰到过。

2. 解压安装与目录结构深度解读

2.1 tar.gz解压命令的“隐性坑”

解压Tomcat这种tar.gz压缩包,标准命令就一个:

tar -zxvf apache-tomcat-8.5.35.tar.gz -C /opt/

这里有个细节值得注意:-C /opt/指定了解压目标目录,如果你不写,它会直接解压到当前目录。很多人习惯先cd到某个目录再解压,这没问题,但解压出来的文件夹名字是apache-tomcat-8.5.35,又长又啰嗦。我通常的做法是先解压,再软链一个短名字:

ln -s /opt/apache-tomcat-8.5.35 /opt/tomcat

后续所有路径都用/opt/tomcat,配置文件里写绝对路径也清爽很多。升级版本时,只需要把软链切到新目录,回滚就是一条命令的事,这个习惯帮我省了不少时间。

解压时还有一个容易忽略的点:tar.gz在解压过程中会保留文件的属主和权限信息。你用什么用户解压,得到的文件属主就是谁。我建议用专门的tomcat用户来部署和运行,而不是直接用root,这样即使Tomcat被攻破,攻击者拿到的也只是tomcat用户的权限,影响面小很多。

创建tomcat用户:

useradd -r -s /sbin/nologin tomcat chown -R tomcat:tomcat /opt/apache-tomcat-8.5.35

2.2 Tomcat目录结构逐层拆解

解压完之后,很多人看着一堆文件夹就懵了,不知道哪个是干嘛的。我整理过一份目录速查表,对照着看就清晰了:

目录/文件作用说明
bin/存放启动、关闭脚本,包括startup.sh、shutdown.sh、catalina.sh
conf/核心配置文件目录,server.xml、web.xml、context.xml都在这里
lib/Tomcat运行所需的jar包,以及你额外补充的JDBC驱动等
logs/运行日志、访问日志、GC日志的输出目录
temp/临时文件目录,Tomcat自动管理,不用手动干预
webapps/存放你的Web应用,把war包扔进来就能自动部署
work/JSP编译后的class文件存放目录,缓存作用,可清理但别删除
LICENSE、NOTICE、RELEASE-NOTES版本信息和许可证文件

这里面最重要的就是conf/server.xml,Tomcat所有网络相关的配置都在这一个文件里。默认监听8080端口、HTTP/1.1协议,连接池参数等等都可以在这里调整。

还有一个很多人不知道的细节:Tomcat 8.5.x默认开启了org.apache.catalina.startup.ContextConfig的JAR扫描,这会导致启动慢,尤其在lib目录下jar包很多的时候。如果不需要扫描注解,可以在conf/context.xml里配置JarScanner关闭扫描,启动速度能有明显提升。

3. JDK版本选择与Java环境配置

3.1 8.5.35对JDK版本的硬性要求

Tomcat 8.5.x这一代有点特殊,它横跨了Java 7到Java 11的演进。具体到8.5.35这个版本,官方Release Notes写得很清楚:运行环境要求Java 7及以上版本,但如果你要完整支持HTTP/2、TLS 1.3这些新特性,建议至少用Java 8。

我的实际建议是:生产环境直接上Java 8,不要用Java 7,更不要用Java 11(除非你明确测试过兼容性)。原因有三个:

  • Java 8是目前Tomcat 8.5.x用户中占比最高的组合,社区踩坑案例最多,遇到问题最好搜到答案;
  • Java 8的JVM参数和GC调优资料最丰富,方便你做后续优化;
  • Tomcat 8.5.35发布时Java 11刚出来不久,官方对这个组合的测试覆盖度不如Java 8充分。

JDK选择上,OpenJDK 8或者Auth的JDK 8都可以。注意架构别选错,x86_64就下x86_64的包,ARM就下ARM的包,下载错了解压就报错。

3.2 JAVA_HOME配置的三种方式

Tomcat启动脚本靠JAVA_HOME环境变量找到JDK,这一步配置不好,后面启动时铁定报Neither the JAVA_HOME nor the JRE_HOME environment variable is defined错误。

配置JAVA_HOME有三种方式,适用场景不同:

第一种,写入/etc/profile,全系统生效:

export JAVA_HOME=/usr/local/jdk1.8.0_202 export PATH=$JAVA_HOME/bin:$PATH

改完执行source /etc/profile让配置立即生效。这种方式适合一台机器只跑一个Java版本的情况。

第二种,写在setenv.sh里,只对Tomcat生效:

vim /opt/tomcat/bin/setenv.sh

内容这样写:

JAVA_HOME=/usr/local/jdk1.8.0_202 JRE_HOME=$JAVA_HOME/jre

这个文件默认不存在,需要手动创建。这种方式最推荐,因为它不会影响机器上其他Java程序,而且后面调整JVM内存参数也在这同一个文件里加,管理起来很集中。

第三种,改catalina.sh,直接在启动脚本里写死。不推荐,因为升级Tomcat版本时这个文件会被覆盖,你的配置就白写了。

我会很明确地说:生产环境用第二种,配合systemd服务一起用,这是最干净、最可控的方案。

4. 启动前的关键调整与性能参数

4.1 端口冲突、内存参数、启动权限,三个先头兵

启动之前,先检查8080端口是否被占用:

ss -lntp | grep 8080

如果端口被占用,要么杀掉占用的进程,要么修改conf/server.xml里的<Connector port="8080",改成你想要的端口。

然后是内存参数。Tomcat默认的JVM内存设置偏保守,-Xms-Xmx默认只有几百MB,并发上来之后频繁GC,性能会非常难看。我的建议是根据机器实际内存调整,在setenv.sh里添加:

JAVA_OPTS="-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Djava.security.egd=file:/dev/./urandom"

解释一下这些参数的含义:

  • -Xms512m:JVM初始堆内存512MB,启动时直接分配,避免运行时动态扩容带来的性能损耗;
  • -Xmx1024m:JVM最大堆内存1GB,超过这个值就会抛出OutOfMemoryError;
  • -XX:MetaspaceSize-XX:MaxMetaspaceSize:Java 8里方法区(存放类元数据)的大小限制,默认无上限,但设置一个合理值可以避免内存被无限制吃光;
  • -Djava.security.egd=file:/dev/./urandom:这行很关键,Tomcat在生成Session ID时会用到SecureRandom,如果用/dev/random,在高并发或系统熵不足的情况下会阻塞很久,改成/dev/urandom后启动速度和响应速度都会正常。

还有一个每次新装Tomcat都会踩的坑:权限。如果你用root解压后直接启动,Tomcat以root身份运行,这在生产环境是很危险的事。但我前面已经创建了tomcat用户,再改一下目录属主:

chown -R tomcat:tomcat /opt/tomcat su -s /bin/bash tomcat -c "/opt/tomcat/bin/startup.sh"

这样Tomcat就是tomcat用户身份下运行的,后顾之忧少了很多。

4.2 通过systemd管理Tomcat,告别裸启动

startup.sh启动Tomcat最大的痛点是:关掉终端窗口,进程可能被挂断,而且开机不会自动启动,进程崩溃了也不会自动拉起。生产环境一定要用systemd来管理。

创建一个service文件/etc/systemd/system/tomcat.service

[Unit] Description=Apache Tomcat 8.5.35 After=network.target [Service] Type=forking User=tomcat Group=tomcat Environment="JAVA_HOME=/usr/local/jdk1.8.0_202" Environment="CATALINA_HOME=/opt/tomcat" Environment="CATALINA_BASE=/opt/tomcat" ExecStart=/opt/tomcat/bin/startup.sh ExecStop=/opt/tomcat/bin/shutdown.sh Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target

这里有几个点要特别注意:

  • Type=forking不能乱改,因为startup.sh启动后会立即返回,真正的Tomcat进程是fork出来的子进程,这是Tomcat启动脚本的默认行为;
  • Environment变量要在service文件里写清楚,避免Tomcat找不到JAVA_HOME;
  • Restart=on-failure是核心配置,进程异常退出后10秒自动拉起,这个容错机制在生产环境太重要了。

配置完成后执行:

systemctl daemon-reload systemctl enable tomcat systemctl start tomcat

启用开机自启,今后机器重启后Tomcat会自动起来,不用再手动去执行startup.sh了。

5. 启动验证与常见故障排查

5.1 三位一体验证启动状态

服务启动之后,别只看“Active: active (running)”就完了,完整验证要覆盖三个层面。

第一层,确认进程存在:

ps -ef | grep tomcat

第二层,确认端口在监听:

ss -lntp | grep 8080

第三层,确认应用真正响应了:

curl -I http://localhost:8080

看到HTTP/1.1 200 OK,才说明Web层面是通的。只看端口监听就以为成功了,有时候会漏掉Tomcat能启动但应用加载失败的情况。

访问http://服务器IP:8080验证更直观,如果IP访问不通,原因大概率是防火墙没放行8080端口。CentOS 7用firewalld,命令是:

firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload

Ubuntu用的是ufw:

ufw allow 8080/tcp

这些基础网络检查往往比Tomcat本身的配置更耗时间,我排查过很多“Tomcat启动不了”最终都是防火墙或者安全组规则的问题。

5.2 从实际报错到解决方案:一份排查速查表

把部署过程中经常遇到的报错信息、排查思路和解决办法整理成了一张表:

报错/现象可能原因解决办法
Neither the JAVA_HOME nor the JRE_HOME...没有正确配置JAVA_HOME在setenv.sh或service文件中设置JAVA_HOME
The JRE_HOME environment variable is not defined correctlyJRE_HOME指向的路径不存在或错误检查$JAVA_HOME/jre目录是否存在,确认JDK安装完整
Port 8080 required by Tomcat 8.5.35 is already in use8080端口被占用ss -lntp看占用进程,换端口或杀进程
java.net.BindException: Permission denied绑定了1024以下端口,非root用户无权限要么改用高位端口,要么用authbindsetcap授权
Access denied for user 'root'@'localhost'数据源配置的用户名密码错误检查context.xml或JNDI数据源配置
SEVERE: Error deploying web application...应用本身的web.xml或jar包冲突解压war包看详细异常,检查lib目录下是否有重复/冲突jar
启动极慢,日志卡在“Creation of SecureRandom instance”JVM使用/dev/random,熵不足导致阻塞JAVA_OPTS里加-Djava.security.egd=file:/dev/./urandom
内存溢出OutOfMemoryError: Java heap space堆内存不够调整-Xmx参数,排查应用是否内存泄漏
看不到应用,manager页面403未配置manager-gui角色用户conf/tomcat-users.xml里添加对应角色和用户
中文乱码URI编码或JVM默认编码不对Connector加URIEncoding="UTF-8",确保JVM使用UTF-8

这张表基本覆盖了我这几年部署Tomcat遇到的大部分问题。遇到报错,第一反应应该是去看logs/catalina.outlogs/localhost.log,不要瞎猜。Tomcat日志信息算给得相当详细了,把异常堆栈看明白,问题就已经解决了一半。

5.3 一次实际的部署排错记录

有一次我部署一个老系统到新服务器,Tomcat起来后进程正常、端口也在监听,但访问就是404。我查看logs/catalina.out没有任何报错,logs/localhost.log里也没有异常。后来想了一下,把webapps里的ROOT目录删了,重新把war包丢进去,访问就正常了。

原因是旧服务器上ROOT目录里残留了旧版本的静态文件,Tomcat启动时直接读取了已有解压目录,没有用新war包重新解压。遇到应用没更新、访问还是旧内容的情况,先清理webapps下对应的解压目录和work目录下的缓存,再把war包重新放进去,这个问题就解决了。

6. 部署完成后还需要做的事

6.1 多实例部署的思路

如果你要在一台机器上跑多个Tomcat实例,比如测试环境和预发布环境共用一台服务器,最优雅的方案不是把安装包复制好几份,而是用一份程序文件配上多个独立的运行目录。

做法是保留一个/opt/tomcat作为程序目录,然后创建多个CATALINA_BASE目录,每个目录里包含conflogswebappstmpwork这几个目录。启动时用:

/opt/tomcat/bin/startup.sh -Dcatalina.base=/opt/instance1

这种方式的好处是程序文件只维护一份,升级时只更新/opt/tomcat下的bin和lib目录,各实例的配置和部署内容互不干扰。多实例之间通过不同的端口和不同的server.xml隔离。

6.2 版本升级的一点个人建议

Tomcat 8.5.35这个版本说实话是2019年发布的,到现在已经积累了不少安全补丁和bug修复。如果你是在生产环境使用,我真心建议你关注一下官方发布的安全公告,在条件允许的情况下升级到8.5系列的最新版本。

升级的方式很简单,下载新版本tar.gz,解压后替换掉旧版本的bin和lib目录,conf目录单独备份出来,对比一下配置差异后复用。因为8.5.x系列内部的配置结构基本没有变化,这种原地升级方式我用过很多次,没有出过问题。

如果你还在用Tomcat 7或者更老的版本,那更值得找个时间升级到8.5系列,至少协议、安全加密、性能方面都有明显的提升。JDK版本也尽量保持到8或以上,别让老旧的运行环境成为系统的短板。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 4:27:01

AI Bot Scraper实战:突破SSE流与浏览器限制,结构化抓取ChatGPT对话

做数据分析的人大概都动过这个念头&#xff1a;能不能把 ChatGPT 的回答批量抓下来&#xff0c;整理成结构化数据&#xff0c;直接喂给下一步流程&#xff1f;我自己第一次尝试的时候&#xff0c;天真地以为就是个普通爬虫的活儿&#xff0c;结果发现页面上的回答倒是看得见&am…

作者头像 李华
网站建设 2026/9/9 4:25:23

智能AR眼镜怎么选?四款热门型号深度横评与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:25:10

入门微单vs二十倍专业器材:实拍差距到底有多大

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:24:23

鲸鱼算法求解线性规划:罚函数设计与Python实现

1. 为什么要用鲸鱼算法去解线性规划 1.1 线性规划不是已经有标准解法了吗 线性规划是我接触运筹学和数学建模时最先遇到的优化模型。标准形式很简单&#xff0c;目标函数和约束条件都是线性的&#xff0c;例如&#xff1a; 最大化 c^T x &#xff0c;满足 A x < b &am…

作者头像 李华
网站建设 2026/9/9 4:23:43

工控单板Linux定制:eMMC分区、A/B OTA升级与OverlayFS恢复出厂

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:23:36

Agent技能管理进化:从散乱提示词到技能包时代

前阵子我在整理一个维护了半年的 Agent 项目&#xff0c;发现里面积了 17 份相互引用的提示词文档、8 个用途不明的 shell 脚本&#xff0c;还有一份早就没人更新的 README。真正让我意识到事情失控的瞬间&#xff0c;是当我想把其中一套“客户周报自动摘要”流程复制到另一个项…

作者头像 李华