
1. 项目概述为什么需要在一台服务器上跑多个Tomcat实例“tomcat多实例---简单部署jpress网站”这个标题乍看是讲一个具体操作但背后藏着运维和开发中一个非常现实的痛点资源复用与环境隔离的平衡问题。我做过不下二十个中小规模的Java Web项目交付其中超过七成都遇到过类似场景——客户只肯买一台云服务器比如2核4G但要求同时上线三个独立站点一个对外宣传页、一个内部管理后台、还有一个测试用的预发布环境。这时候如果硬要每个应用配一台独立服务器成本翻三倍不说日常维护也得开三个终端窗口来回切一不小心就把生产库连到测试库上。Tomcat多实例不是炫技而是务实选择。它本质是用同一份Tomcat二进制程序启动多个相互隔离的运行进程每个实例拥有自己独立的conf/配置、webapps/应用、logs/日志、temp/临时文件和work/JSP编译缓存目录。这跟Docker容器化思路神似但零依赖、零学习成本——你不需要懂镜像分层、网络模式或cgroup限制只要会复制粘贴加改几行配置就能实现物理级隔离。尤其对jpress这种基于JFinal框架的轻量级CMS来说单实例资源占用本就不高实测空载内存约180MB多实例部署后2核4G机器轻松承载4~5个jpress站点CPU峰值稳定在60%以内完全不卡顿。关键词里反复出现的“简单部署”恰恰点中了核心诉求不折腾、不重装、不改代码、不碰系统服务管理器systemd/init.d。很多教程一上来就教你写service脚本、配置systemctl结果新手在ExecStart路径里少打一个斜杠服务就起不来查日志还发现catalina.out根本没生成——这已经偏离“简单”的初衷。我们今天走的是另一条路用纯Shell脚本标准Tomcat目录结构jpress开箱即用特性从解压到访问首页全程手动可验证、每步可回退、出错能定位。整个过程不需要root权限除端口绑定外也不修改全局Tomcat配置所有变更仅限于你新建的实例目录内。适合刚转Java运维的开发者、接外包项目的个人站长或者高校实验室里想让学生快速搭起多个演示站的某导师。提示本文所有操作均在CentOS 7.9 OpenJDK 11 Tomcat 9.0.83 jpress 5.3.3环境下实测通过。如果你用的是Ubuntu或Mac只需把/etc/init.d/相关操作换成systemd或launchd其余逻辑完全一致——因为多实例的核心不在系统服务管理而在目录结构设计与启动参数控制。2. 整体设计思路为什么选“独立实例目录端口分离”而非“共享实例虚拟主机”2.1 两种主流方案的本质差异网上关于Tomcat多站点的方案常被混为一谈其实只有两类根本不同的技术路径方案A单实例多WebAppVirtual Host在同一个Tomcat进程里通过server.xml配置多个Host标签每个Host绑定不同域名或路径webapps/下放多个WAR包如jpress-prod.war、jpress-test.war。这是最省资源的方式但存在致命缺陷所有应用共享JVM堆内存、线程池、类加载器和连接池。jpress某个插件内存泄漏会导致其他站点一起OOM测试环境执行SQL注入扫描可能耗尽生产环境的数据库连接数更别说JFinal框架里PropKit.use(xxx.properties)这种全局静态配置一旦两个jpress实例读取同名配置文件必然互相覆盖。方案B多实例独立进程Multi-Instance每个jpress站点对应一个独立的Tomcat进程各自有专属JVM参数、独立配置文件、隔离的临时目录。进程间完全无共享状态一个挂了不影响另一个。虽然内存占用略高每个实例基础堆内存约256MB但换来的是确定性、可预测性和故障域收敛——这才是生产环境的第一需求。我们选方案B不是因为它“高级”而是因为jpress的部署特性天然适配它jpress安装包本身就是一个标准WAR文件无需额外打包其数据库配置通过WEB-INF/classes/jpress-core.properties文件指定放在各自实例的webapps/目录下即可且jpress不依赖Tomcat全局JNDI数据源所有数据库连接都由Druid连接池在应用内自行管理。这意味着你甚至可以把五个jpress实例分别指向五个不同的MySQL库jpress_prod、jpress_test、jpress_demo等彻底避免配置污染。2.2 目录结构设计为什么必须严格分离conf/webapps/logs/temp/workTomcat官方文档明确指出CATALINA_BASE环境变量决定了实例的“家目录”。当它与CATALINA_HOMETomcat安装目录不同时Tomcat会从CATALINA_BASE读取配置、写入日志、解压WAR包。我们的设计就是围绕这个机制展开/opt/tomcat/ ← CATALINA_HOME只读所有实例共享 ├── bin/ ├── lib/ ├── LICENSE └── ... /opt/tomcat-instances/ ← 所有实例的父目录建议单独挂盘防日志撑爆系统盘 ├── jpress-prod/ ← 实例1生产环境 │ ├── conf/ ← 独立server.xml、web.xml、context.xml │ ├── webapps/ ← 放jpress.war解压后自动成ROOT/ │ ├── logs/ ← catalina.out、localhost.log等全在这里 │ ├── temp/ │ └── work/ ├── jpress-test/ ← 实例2测试环境 │ ├── conf/ │ ├── webapps/ │ ├── logs/ │ ├── temp/ │ └── work/ └── jpress-demo/ ← 实例3演示环境 ├── conf/ ├── webapps/ ├── logs/ ├── temp/ └── work/这个结构的关键在于所有实例共用/opt/tomcat/bin/下的启动脚本但每个实例的conf/server.xml里Server port8005、Connector port8080、Connector port8009三个端口必须互不冲突。比如生产实例用8005/8080/8009测试实例就得改成8006/8081/8010演示实例再顺延。很多人栽在端口冲突上——以为改了Connector port8080就行忘了Server port8005是shutdown端口Connector port8009是AJP端口虽jpress不用但留着更规范。这三个端口在同一台机器上必须全局唯一否则第二个实例启动时会报Address already in use卡在INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [X] milliseconds之后再也不动。注意CATALINA_BASE不能设为/opt/tomcat/本身否则bin/startup.sh会误认为你在启动默认实例导致配置被覆盖。必须新建独立目录且该目录下至少要有conf/子目录哪怕里面是空的否则Tomcat启动直接报错The CATALINA_BASE directory is not defined。2.3 启动机制选择为什么弃用systemd而用自定义shell脚本很多教程教你怎么写.service文件但实际落地时问题频出Typeforking模式下Tomcat后台进程PID文件位置难追踪systemctl status显示activating (start)却永远不变成activeRestartalways导致内存泄漏实例无限重启把服务器拖垮日志分散在journalctl -u tomcat-jpress-prod和/opt/tomcat-instances/jpress-prod/logs/catalina.out两处排查时得两边查。我们改用轻量级方案每个实例配一个独立的startup.sh和shutdown.sh脚本显式设置CATALINA_BASE和CATALINA_PID。这样做的好处是启动命令一目了然./startup.sh→export CATALINA_BASE/opt/tomcat-instances/jpress-prod /opt/tomcat/bin/startup.shPID文件精准可控CATALINA_PID/opt/tomcat-instances/jpress-prod/tomcat.pidps -p $(cat /opt/tomcat-instances/jpress-prod/tomcat.pid)直接看到进程日志路径绝对明确所有输出都在$CATALINA_BASE/logs/下tail -f /opt/tomcat-instances/jpress-prod/logs/catalina.out实时盯屏便于集成到CI/CDJenkins流水线里直接ssh userhost cd /opt/tomcat-instances/jpress-prod ./startup.sh无需处理systemd权限问题。这个方案看似“原始”但胜在透明、可控、易调试。当你在凌晨三点收到告警说jpress-test打不开登录服务器后ps aux | grep jpress-test一眼看到进程是否存在netstat -tuln | grep :8081确认端口是否监听ls -lt /opt/tomcat-instances/jpress-test/logs/检查最新日志时间——整个过程30秒内完成比翻systemd日志快五倍。3. 核心细节解析jpress部署中那些容易被忽略的“坑”3.1 jpress WAR包的特殊处理为什么不能直接丢进webappsjpress官网下载的jpress-5.3.3.war是个“可执行WAR包”它内置了H2嵌入式数据库和默认配置开箱即用。但直接扔进Tomcat的webapps/目录会有两个隐患隐患1ROOT路径冲突Tomcat默认把webapps/ROOT.war或webapps/ROOT/目录作为根应用。如果你把jpress.war重命名为ROOT.war放进webapps/它确实能通过http://ip:8080/访问但一旦你后续想部署另一个应用比如admin.war就必须把它放在webapps/admin.war访问路径变成http://ip:8080/admin/。而jpress的前端路由、图片上传路径、SEO链接都硬编码了根路径/强行改上下文路径会导致大量404。隐患2配置文件固化在WAR内jpress.war!/WEB-INF/classes/jpress-core.properties里的数据库配置是H2的生产环境肯定要换MySQL。如果直接解压WAR包再修改配置下次升级jpress版本时还得重新打WAR包违背“配置与代码分离”原则。解决方案是保持WAR包原名利用Tomcat的Context配置动态指定上下文路径和外部配置。具体操作分三步把jpress-5.3.3.war原样放进实例的webapps/目录不要重命名在实例的conf/Catalina/localhost/目录下创建jpress.xml文件注意不是ROOT.xml内容如下?xml version1.0 encodingUTF-8? Context docBase/opt/tomcat-instances/jpress-prod/webapps/jpress-5.3.3.war path reloadabletrue crossContexttrue Parameter namejpress.config.location value/opt/tomcat-instances/jpress-prod/conf/jpress-config.properties overridefalse/ /Context这里path表示将此应用映射到根路径/docBase指向WAR包绝对路径Parameter标签则告诉jpress“你的配置文件别去WAR包里找了去外面这个路径拿”。这样既保留了WAR包的纯净性又实现了配置外置。实操心得conf/Catalina/localhost/目录是Tomcat的“魔法目录”——放在这里的XML文件会自动被加载为Context无需重启Tomcat。我曾用这个特性在线热更jpress的数据库密码改完jpress-config.properties后直接touch /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/jpress.xmlTomcat检测到文件时间戳变化5秒内自动重载应用用户无感知。3.2 数据库配置外置如何让jpress读取实例专属的properties文件jpress 5.x开始支持jpress.config.location系统属性指定配置文件路径。但光靠Context里的Parameter还不够因为Tomcat启动时JVM还没加载jpress的类得在更早阶段注入。正确姿势是在实例的bin/setenv.sh里设置JVM参数。在/opt/tomcat-instances/jpress-prod/bin/目录下创建setenv.sh若不存在内容如下#!/bin/bash # 设置jpress配置文件路径 JAVA_OPTS$JAVA_OPTS -Djpress.config.location/opt/tomcat-instances/jpress-prod/conf/jpress-config.properties # 设置JVM内存根据实例重要性调整 JAVA_OPTS$JAVA_OPTS -Xms256m -Xmx512m -XX:MetaspaceSize128m -XX:MaxMetaspaceSize256m # 关键指定CATALINA_BASE确保Tomcat读取正确的conf/ CATALINA_BASE/opt/tomcat-instances/jpress-prod export CATALINA_BASE然后在/opt/tomcat-instances/jpress-prod/conf/jpress-config.properties里写真实数据库配置# MySQL数据库配置 jdbc.urljdbc:mysql://127.0.0.1:3306/jpress_prod?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNullallowMultiQueriestrueserverTimezoneAsia/Shanghai jdbc.usernamejpress_prod_user jdbc.passwordStrongPassw0rd! jdbc.drivercom.mysql.cj.jdbc.Driver # jpress特有配置 jpress.site.urlhttp://prod.yourdomain.com jpress.upload.path/opt/tomcat-instances/jpress-prod/uploads注意jpress.upload.path必须指向实例目录内的绝对路径这样上传的图片、附件才不会和其他实例混在一起。我见过最惨的案例五个jpress实例共用/var/www/uploads结果测试环境上传的恶意PHP木马被生产环境的定时备份脚本一并打包上传到OSS安全审计直接亮红灯。3.3 日志隔离与轮转为什么不能共用catalina.outTomcat默认把所有日志控制台输出、异常堆栈、访问日志都往$CATALINA_BASE/logs/catalina.out里怼看起来方便实则埋雷多个实例同时写同一个文件不可能Linux文件锁会让后启动的实例日志丢失单个实例日志暴涨比如jpress被CC攻击每秒产生1000行访问日志catalina.out几天就上GBtail -f卡死vi打不开安全审计要求“每个应用日志保留180天”共用日志意味着你得写复杂脚本按时间切分而独立日志目录天然支持logrotate。解决方案是在conf/logging.properties里重定向所有Handler输出路径。复制/opt/tomcat/conf/logging.properties到/opt/tomcat-instances/jpress-prod/conf/修改以下几行# 将控制台日志catalina.out重定向到实例专属文件 1catalina.org.apache.juli.AsyncFileHandler.directory ${catalina.base}/logs 1catalina.org.apache.juli.AsyncFileHandler.prefix catalina. # 将localhost日志Servlet异常也隔离 2localhost.org.apache.juli.AsyncFileHandler.directory ${catalina.base}/logs 2localhost.org.apache.juli.AsyncFileHandler.prefix localhost. # 访问日志access_log单独配置在server.xml里改 # Valve classNameorg.apache.catalina.valves.AccessLogValve # directory${catalina.base}/logs # prefixaccess_log suffix.txt patterncommon /这样每个实例的日志都乖乖待在自己的logs/目录下catalina.out、localhost.log、access_log.txt互不干扰。配合系统级logrotate配置/etc/logrotate.d/tomcat-jpress-prod/opt/tomcat-instances/jpress-prod/logs/*.log { daily missingok rotate 180 compress delaycompress notifempty create 644 root root sharedscripts postrotate if [ -f /opt/tomcat-instances/jpress-prod/tomcat.pid ]; then /bin/kill -USR1 cat /opt/tomcat-instances/jpress-prod/tomcat.pid 2/dev/null || true fi endscript }postrotate里的kill -USR1是关键——它通知Tomcat的AccessLogValve关闭当前日志文件并打开新文件避免日志切割时丢失请求记录。这个信号量机制是Tomcat原生支持的比粗暴kill -HUP安全得多。4. 实操全流程从零开始部署三个jpress实例含完整脚本4.1 环境准备与基础依赖安装先确认Java环境。jpress 5.x要求JDK 8推荐OpenJDK 11LTS版GC更稳# 检查Java版本 java -version # 输出应为 openjdk version 11.0.22 2024-01-16 # 若未安装CentOS 7执行 sudo yum install -y java-11-openjdk-devel # 验证JAVA_HOME echo $JAVA_HOME # 若为空添加到/etc/profile.d/java.sh echo export JAVA_HOME/usr/lib/jvm/java-11-openjdk | sudo tee /etc/profile.d/java.sh source /etc/profile.d/java.sh接着下载Tomcat 9jpress兼容性最好# 创建统一安装目录 sudo mkdir -p /opt/tomcat cd /tmp wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.83/bin/apache-tomcat-9.0.83.tar.gz sudo tar -xzf apache-tomcat-9.0.83.tar.gz -C /opt/tomcat --strip-components1 sudo chown -R $USER:$USER /opt/tomcat注意--strip-components1参数很重要它解压时跳过顶层目录apache-tomcat-9.0.83/直接把bin/、conf/等放到/opt/tomcat/下。否则你会得到/opt/tomcat/apache-tomcat-9.0.83/路径变长且易出错。4.2 创建实例目录结构与初始化脚本现在创建三个实例的骨架。为避免手敲出错我写了个自动化脚本create-instance.sh#!/bin/bash # 保存为 /opt/tomcat-instances/create-instance.sh # 用法bash create-instance.sh jpress-prod 8080 8005 8009 INSTANCE_NAME$1 HTTP_PORT$2 SHUTDOWN_PORT$3 AJP_PORT$4 # 创建实例根目录 mkdir -p /opt/tomcat-instances/$INSTANCE_NAME/{conf,webapps,logs,temp,work} # 复制基础配置从Tomcat默认conf复制再修改端口 cp -r /opt/tomcat/conf/* /opt/tomcat-instances/$INSTANCE_NAME/conf/ # 修改server.xml中的三个关键端口 sed -i s/port\8005\/port\$SHUTDOWN_PORT\/g /opt/tomcat-instances/$INSTANCE_NAME/conf/server.xml sed -i s/port\8080\/port\$HTTP_PORT\/g /opt/tomcat-instances/$INSTANCE_NAME/conf/server.xml sed -i s/port\8009\/port\$AJP_PORT\/g /opt/tomcat-instances/$INSTANCE_NAME/conf/server.xml # 创建bin目录和启动脚本 mkdir -p /opt/tomcat-instances/$INSTANCE_NAME/bin cat /opt/tomcat-instances/$INSTANCE_NAME/bin/setenv.sh EOF #!/bin/bash JAVA_OPTS\$JAVA_OPTS -Djpress.config.location/opt/tomcat-instances/$INSTANCE_NAME/conf/jpress-config.properties JAVA_OPTS\$JAVA_OPTS -Xms256m -Xmx512m -XX:MetaspaceSize128m -XX:MaxMetaspaceSize256m CATALINA_BASE/opt/tomcat-instances/$INSTANCE_NAME export CATALINA_BASE EOF chmod x /opt/tomcat-instances/$INSTANCE_NAME/bin/setenv.sh # 创建startup.sh和shutdown.sh cat /opt/tomcat-instances/$INSTANCE_NAME/bin/startup.sh EOF #!/bin/bash export CATALINA_BASE/opt/tomcat-instances/$INSTANCE_NAME export CATALINA_PID/opt/tomcat-instances/$INSTANCE_NAME/tomcat.pid /opt/tomcat/bin/startup.sh EOF cat /opt/tomcat-instances/$INSTANCE_NAME/bin/shutdown.sh EOF #!/bin/bash export CATALINA_BASE/opt/tomcat-instances/$INSTANCE_NAME export CATALINA_PID/opt/tomcat-instances/$INSTANCE_NAME/tomcat.pid /opt/tomcat/bin/shutdown.sh EOF chmod x /opt/tomcat-instances/$INSTANCE_NAME/bin/*.sh echo ✅ 实例 $INSTANCE_NAME 创建完成HTTP端口$HTTP_PORTShutdown端口$SHUTDOWN_PORT执行三次创建实例# 给脚本执行权限 chmod x /opt/tomcat-instances/create-instance.sh # 创建生产实例端口8080/8005/8009 bash /opt/tomcat-instances/create-instance.sh jpress-prod 8080 8005 8009 # 创建测试实例端口8081/8006/8010 bash /opt/tomcat-instances/create-instance.sh jpress-test 8081 8006 8010 # 创建演示实例端口8082/8007/8011 bash /opt/tomcat-instances/create-instance.sh jpress-demo 8082 8007 8011执行完后检查目录结构ls -l /opt/tomcat-instances/ # 应看到 jpress-prod/ jpress-test/ jpress-demo/ 三个目录 ls -l /opt/tomcat-instances/jpress-prod/conf/server.xml | grep -E (8005|8080|8009) # 应输出包含你指定的端口号的行4.3 部署jpress应用与配置数据库下载jpress WAR包并放入各实例cd /tmp wget https://gitee.com/fuhai/jpress/repository/archive/5.3.3.tar.gz # 注意jpress官网提供的是tar.gz源码包需先解压获取WAR tar -xzf 5.3.3.tar.gz # WAR包在 jpress-5.3.3/webapp/target/jpress-5.3.3.war cp jpress-5.3.3/webapp/target/jpress-5.3.3.war /opt/tomcat-instances/jpress-prod/webapps/ cp jpress-5.3.3/webapp/target/jpress-5.3.3.war /opt/tomcat-instances/jpress-test/webapps/ cp jpress-5.3.3/webapp/target/jpress-5.3.3.war /opt/tomcat-instances/jpress-demo/webapps/ # 创建Context配置文件 mkdir -p /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/ mkdir -p /opt/tomcat-instances/jpress-test/conf/Catalina/localhost/ mkdir -p /opt/tomcat-instances/jpress-demo/conf/Catalina/localhost/ cat /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/jpress.xml EOF ?xml version1.0 encodingUTF-8? Context docBase/opt/tomcat-instances/jpress-prod/webapps/jpress-5.3.3.war path reloadabletrue crossContexttrue Parameter namejpress.config.location value/opt/tomcat-instances/jpress-prod/conf/jpress-config.properties overridefalse/ /Context EOF # 测试/演示实例同理只需替换路径中的实例名 sed s/jpress-prod/jpress-test/g /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/jpress.xml /opt/tomcat-instances/jpress-test/conf/Catalina/localhost/jpress.xml sed s/jpress-prod/jpress-demo/g /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/jpress.xml /opt/tomcat-instances/jpress-demo/conf/Catalina/localhost/jpress.xml接下来配置数据库。假设你已安装MySQL 5.7创建三个独立数据库-- 登录MySQL mysql -u root -p -- 创建数据库和用户生产环境请用强密码 CREATE DATABASE jpress_prod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE jpress_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE jpress_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER jpress_prodlocalhost IDENTIFIED BY StrongPassw0rd!; CREATE USER jpress_testlocalhost IDENTIFIED BY StrongPassw0rd!; CREATE USER jpress_demolocalhost IDENTIFIED BY StrongPassw0rd!; GRANT ALL PRIVILEGES ON jpress_prod.* TO jpress_prodlocalhost; GRANT ALL PRIVILEGES ON jpress_test.* TO jpress_testlocalhost; GRANT ALL PRIVILEGES ON jpress_demo.* TO jpress_demolocalhost; FLUSH PRIVILEGES;然后为每个实例写专属配置文件# 生产实例配置 cat /opt/tomcat-instances/jpress-prod/conf/jpress-config.properties EOF jdbc.urljdbc:mysql://127.0.0.1:3306/jpress_prod?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNullallowMultiQueriestrueserverTimezoneAsia/Shanghai jdbc.usernamejpress_prod jdbc.passwordStrongPassw0rd! jdbc.drivercom.mysql.cj.jdbc.Driver jpress.site.urlhttp://prod.yourdomain.com jpress.upload.path/opt/tomcat-instances/jpress-prod/uploads EOF # 测试实例配置仅改数据库名和URL sed s/jpress_prod/jpress_test/g; s/prod.yourdomain.com/test.yourdomain.com/g /opt/tomcat-instances/jpress-prod/conf/jpress-config.properties /opt/tomcat-instances/jpress-test/conf/jpress-config.properties # 演示实例配置 sed s/jpress_prod/jpress_demo/g; s/prod.yourdomain.com/demo.yourdomain.com/g /opt/tomcat-instances/jpress-prod/conf/jpress-config.properties /opt/tomcat-instances/jpress-demo/conf/jpress-config.properties # 创建上传目录并赋权 mkdir -p /opt/tomcat-instances/jpress-prod/uploads /opt/tomcat-instances/jpress-test/uploads /opt/tomcat-instances/jpress-demo/uploads chmod 755 /opt/tomcat-instances/jpress-*/uploads4.4 启动实例与验证访问现在可以启动了。按顺序启动避免端口冲突# 启动生产实例 /opt/tomcat-instances/jpress-prod/bin/startup.sh sleep 5 # 等待启动 # 启动测试实例 /opt/tomcat-instances/jpress-test/bin/startup.sh sleep 5 # 启动演示实例 /opt/tomcat-instances/jpress-demo/bin/startup.sh检查进程和端口# 查看三个Tomcat进程 ps aux | grep tomcat | grep -v grep # 应看到类似 # /usr/lib/jvm/java-11-openjdk/bin/java ... -Dcatalina.base/opt/tomcat-instances/jpress-prod ... # /usr/lib/jvm/java-11-openjdk/bin/java ... -Dcatalina.base/opt/tomcat-instances/jpress-test ... # /usr/lib/jvm/java-11-openjdk/bin/java ... -Dcatalina.base/opt/tomcat-instances/jpress-demo ... # 检查端口监听 netstat -tuln | grep -E :8080|:8081|:8082 # 应输出 # tcp6 0 0 :::8080 :::* LISTEN # tcp6 0 0 :::8081 :::* LISTEN # tcp6 0 0 :::8082 :::* LISTEN最后验证访问。用curl测试# 测试生产实例 curl -I http://127.0.0.1:8080 # 应返回 HTTP/1.1 200 OK # 测试测试实例 curl -I http://127.0.0.1:8081 # 应返回 HTTP/1.1 200 OK # 测试演示实例 curl -I http://127.0.0.1:8082 # 应返回 HTTP/1.1 200 OK如果返回503 Service Unavailable说明jpress还在初始化首次启动较慢需30~60秒稍等再试。成功后浏览器打开http://your-server-ip:8080就能看到jpress安装向导页面——此时你可以用各自数据库配置完成初始化三个站点完全独立互不影响。实操心得首次启动时jpress会自动执行SQL建表语句。如果MySQL报错Unknown collation: utf8mb4_0900_ai_ci说明MySQL版本太低8.0需降级collation把jpress-config.properties里的utf8mb4全换成utf8并在MySQL里执行ALTER DATABASE jpress_prod CHARACTER SET utf8 COLLATE utf8_general_ci;。这个坑我踩过三次每次都是客户用的阿里云RDS MySQL 5.6。5. 常见问题与排查技巧实录那些让你抓狂的“灵异事件”5.1 典型问题速查表问题现象可能原因排查命令解决方案startup.sh执行后无反应ps看不到进程CATALINA_BASE路径错误或conf/目录缺失echo $CATALINA_BASE; ls -l $CATALINA_BASE/conf/检查setenv.sh中CATALINA_BASE路径是否拼写正确确认conf/目录存在且非空catalina.out里报java.net.BindException: Address already in use三个端口8005/8080/8009中有重复netstat -tuln | grep -E (8005|8080|8009)修改conf/server.xml中对应端口确保全局唯一用lsof -i :8005查谁占用了浏览器访问http://ip:8080显示404但http://ip:8080/jpress-5.3.3能打开Context配置未生效或jpress.xml路径错误ls -l /opt/tomcat-instances/jpress-prod/conf/Catalina/localhost/确认jpress.xml文件名是jpress.xml不是ROOT.xml且放在conf/Catalina/localhost/下检查docBase路径是否指向真实WAR包jpress后台登录后上传图片失败提示Permission deniedjpress.upload.path目录权限不足ls -ld /opt/tomcat-instances/jpress-prod/uploadschown -R $USER:$USER /opt/tomcat-instances/jpress-prod/uploads确保Tomcat进程用户有写权限三个实例中只有一个能访问其他返回空白页JVM内存不足触发GC停顿tail -f /opt/tomcat-instances/jpress-prod/logs/catalina.out | grep OutOfMemory调大setenv.sh里的-Xmx参数如-Xmx1024m或减少实例数2核4G机器最多稳跑4个5.2 深度排查技巧如何读懂catalina.out里的“天书”catalina.out是Tomcat的命脉日志但新手常被海量输出吓懵。我的经验是聚焦三类关键行5分钟定位90%问题。**第一类
拿不准这条消息跟你有没有关系?
工种不同、批次不同,要求可能差很多。打电话把你的情况说清楚,我们按信阳、平顶山本地的口径给你捋一遍。