When configuring Tomcat as a Systemd service on CentOS 7, the service fails to recognize the $JAVA_HOME
environment variable set in /etc/profile.d/setenv.sh
. The service only works when JAVA_HOME
is explicitly declared in the Systemd unit file.
Systemd services don't automatically load shell environment variables because:
- Systemd starts before user login shells
- /etc/profile.d scripts execute during interactive shell initialization
- Service units run in a minimal environment by design
Method 1: Direct Declaration in Unit File (Recommended)
[Service]
Environment=JAVA_HOME=/usr/java/jdk1.8.0_74
Environment=CATALINA_HOME=/opt/tomcat
# Other environment variables...
Method 2: Using EnvironmentFile Directive
[Service]
EnvironmentFile=/etc/sysconfig/tomcat
# Other configurations...
Create /etc/sysconfig/tomcat
:
JAVA_HOME=/usr/java/jdk1.8.0_74
CATALINA_HOME=/opt/tomcat
Method 3: Global Systemd Configuration (Less Preferred)
# Create /etc/systemd/system.conf.d/tomcat-env.conf
[Manager]
DefaultEnvironment="JAVA_HOME=/usr/java/jdk1.8.0_74"
Then run:
systemctl daemon-reload
systemctl restart tomcat
- For service-specific variables: Use Method 1 (direct declaration)
- When sharing variables across services: Use Method 2 (EnvironmentFile)
- Always verify environment with:
systemctl show tomcat --property=Environment
- Consider creating a dedicated tomcat user environment file in
/etc/default/tomcat
To diagnose environment issues:
# Check effective environment
systemctl show tomcat --property=Environment
# Test startup manually with full environment
sudo -u tomcat -E /opt/tomcat/bin/startup.sh
# View systemd execution context
journalctl -u tomcat -b -n 50
For complex deployments, consider using a wrapper script:
#!/bin/bash
source /etc/profile.d/setenv.sh
exec /opt/tomcat/bin/catalina.sh run
Then modify the unit file:
[Service]
ExecStart=/path/to/wrapper.sh
When setting up a Tomcat service with Systemd on CentOS 7, you might encounter a situation where Tomcat fails to recognize the $JAVA_HOME
environment variable despite it being properly set in /etc/profile.d/setenv.sh
. This typically manifests when the Environment=JAVA_HOME
line is omitted from the Systemd service file.
The fundamental reason is that Systemd services don't load user environment files like /etc/profile
or /etc/profile.d/*.sh
. These files are only processed during interactive shell login sessions. Systemd has its own mechanism for environment variables.
There are several robust approaches to ensure Tomcat finds Java:
Method 1: Directly Specify in Service File (Recommended)
The most reliable approach is to explicitly define JAVA_HOME
in your Systemd unit file:
[Service]
Environment=JAVA_HOME=/usr/java/jdk1.8.0_74
# Other environment variables...
Method 2: Use Systemd EnvironmentFile
Create a dedicated environment file and reference it:
# Create environment file
echo "JAVA_HOME=/usr/java/jdk1.8.0_74" > /etc/sysconfig/tomcat
# Modify service file
[Service]
EnvironmentFile=/etc/sysconfig/tomcat
Method 3: Global Systemd Configuration
For system-wide Java settings:
# Create drop-in directory
mkdir -p /etc/systemd/system.conf.d/
# Create java.conf
echo "[Manager]
DefaultEnvironment=\"JAVA_HOME=/usr/java/jdk1.8.0_74\"" > /etc/systemd/system.conf.d/java.conf
# Reload systemd
systemctl daemon-reload
After implementing any of these methods, verify the environment is properly set:
# Check service environment
systemctl show tomcat --property=Environment
# Alternatively, modify ExecStart temporarily
ExecStart=/bin/sh -c 'echo $JAVA_HOME > /tmp/java_home_test; /opt/tomcat/bin/startup.sh'
When dealing with multiple Java versions, consider these enhancements:
# Using alternatives system
alternatives --config java
# Or using update-alternatives
update-alternatives --config java
For more complex environments, you might want to create a symlink:
ln -s /usr/java/jdk1.8.0_74 /usr/java/default
- Always run
systemctl daemon-reload
after modifying service files - Check journal logs with
journalctl -u tomcat -f
- Test environment variables with
systemctl show-environment