不能只靠 /etc/profile 全局覆盖,因 tomcat 启动不重新加载它,且多实例需独立 catalina_home/base;应通过 /etc/profile.d/ 分实例定义变量,并在各 catalina.sh 中按需加载。

直接改 /etc/profile 不够用,批量部署时必须避免手动逐台编辑;核心是把环境变量拆成独立文件、统一注入、按需加载。
为什么不能只靠 /etc/profile 全局覆盖
多个 Tomcat 实例共存时,CATALINA_HOME 和 CATALINA_BASE 必须一一对应且互不干扰。全局写死一个 CATALINA_HOME 会导致所有 startup.sh 都指向同一份安装目录,后续启动必然冲突或覆盖。
- 所有 Tomcat 启动脚本(
catalina.sh)默认只认CATALINA_HOME和CATALINA_BASE这两个变量名 -
/etc/profile是 shell 登录时加载的,但 Tomcat 启动时并不重新 source 它 —— 它只依赖当前 shell 环境中已存在的变量 - 若用
export CATALINA_HOME=/opt/tomcat1写死在/etc/profile,第二台 Tomcat 的startup.sh也会读到这个值,根本不会自动切换
正确做法:用 /etc/profile.d/ 下的独立脚本分实例管理
Linux 下 /etc/profile.d/ 目录中的 .sh 文件会在每次登录时被自动 source,适合做模块化环境变量注入。
- 为每个 Tomcat 实例创建单独的配置文件,例如:
/etc/profile.d/tomcat1.sh、/etc/profile.d/tomcat2.sh - 每个文件只定义该实例所需的变量,不互相污染:
# /etc/profile.d/tomcat1.sh export CATALINA_HOME_1=/opt/tomcat1 export CATALINA_BASE_1=/opt/tomcat1 export TOMCAT_HOME_1=/opt/tomcat1
# /etc/profile.d/tomcat2.sh export CATALINA_HOME_2=/opt/tomcat2 export CATALINA_BASE_2=/opt/tomcat2 export TOMCAT_HOME_2=/opt/tomcat2
- 确保文件有执行权限:
chmod +x /etc/profile.d/tomcat*.sh
关键:修改每个 catalina.sh 让它主动加载对应变量
Tomcat 启动入口是 catalina.sh,它本身不读 /etc/profile.d/,必须显式引入变量。不能只改 startup.sh,因为真正干活的是 catalina.sh。
- 打开
/opt/tomcat1/bin/catalina.sh,在# OS specific support注释下方插入:if [ -z "$CATALINA_HOME" ]; then export CATALINA_HOME=$CATALINA_HOME_1 export CATALINA_BASE=$CATALINA_BASE_1 fi
- 同理,
/opt/tomcat2/bin/catalina.sh插入:if [ -z "$CATALINA_HOME" ]; then export CATALINA_HOME=$CATALINA_HOME_2 export CATALINA_BASE=$CATALINA_BASE_2 fi
- 这样既兼容手动设置的
CATALINA_HOME(优先级更高),又能在未设时 fallback 到预定义实例变量
批量部署时最易忽略的三个点
自动化脚本常在这里翻车:
-
catalina.sh中的判断逻辑必须用[ -z "$CATALINA_HOME" ],而不是[ -z $CATALINA_HOME ](缺少引号会导致空值报错) - 所有
server.xml中的端口(<server port="8005"></server>、<connector port="8080"></connector>、<connector port="8009"></connector>)必须全部改掉,漏一个就会启动失败并报Address already in use - 如果用 Ansible 或 Shell 脚本批量推送,
/etc/profile.d/*.sh文件的 owner 必须是root:root,否则非 root 用户登录时可能因权限问题无法加载











