Resolving Tomcat Systemd Service Failure to Detect $JAVA_HOME on CentOS 7


2 views

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