In modern software development, deploying Java applications on Linux servers is a common practice. This article will detail the deployment process, best practices, and common troubleshooting solutions for Java applications in a Linux environment, helping developers efficiently complete application deployment tasks.
1. Pre-deployment Preparation
1.1 System Environment Check
Before deploying a Java application, it is essential to check the environment configuration of the target server:
# Check operating system version
lsb_release -a
uname -a
# Check Java environment
java -version
echo $JAVA_HOME
# Check memory and CPU
free -h
lscpu
# Check disk space
df -h
# Check network connection
ping -c 4 google.com
1.2 Security Settings
Ensure the server’s security configuration:
# Configure firewall (using ufw as an example)
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 8080 # Application port
# Create a dedicated user to run the application
sudo adduser appuser
sudo usermod -aG sudo appuser
# Set up SSH key authentication (recommended)
mkdir -p /home/appuser/.ssh
chmod 700 /home/appuser/.ssh
# Add public key to authorized_keys file
1.3 Directory Structure Planning
Establishing a reasonable directory structure facilitates management and maintenance:
# Application directory structure
sudo mkdir -p /opt/myapp/{bin,conf,lib,logs,temp}
sudo chown -R appuser:appuser /opt/myapp
# Log directory
sudo mkdir -p /var/log/myapp
sudo chown appuser:appuser /var/log/myapp
# Configuration file directory
sudo mkdir -p /etc/myapp
sudo chown appuser:appuser /etc/myapp
2. Manual Deployment Process
2.1 WAR Package Deployment (for Tomcat)
# 1. Stop Tomcat service
sudo systemctl stop tomcat
# 2. Backup existing application
sudo cp /opt/tomcat/webapps/myapp.war /opt/tomcat/webapps/myapp.war.backup
# 3. Upload new WAR package
scp myapp.war appuser@server:/tmp/
# 4. Deploy application
sudo mv /tmp/myapp.war /opt/tomcat/webapps/
# 5. Start Tomcat service
sudo systemctl start tomcat
# 6. Check deployment status
sudo tail -f /opt/tomcat/logs/catalina.out
2.2 JAR Package Deployment (for Spring Boot applications)
# 1. Upload JAR package
scp myapp.jar appuser@server:/tmp/
# 2. Stop existing application
sudo systemctl stop myapp
# 3. Deploy new version
sudo mv /tmp/myapp.jar /opt/myapp/
sudo chown appuser:appuser /opt/myapp/myapp.jar
# 4. Start application
sudo systemctl start myapp
# 5. Check application status
sudo systemctl status myapp
2.3 Configuration File Management
# Application configuration file
sudo vim /etc/myapp/application.properties
# Environment-specific configuration
sudo vim /etc/myapp/application-prod.properties
# Database configuration
sudo vim /etc/myapp/database.properties
3. Writing Startup Scripts
3.1 Simple Startup Script
Create a basic startup script:
#!/bin/bash
# /opt/myapp/bin/start.sh
APP_NAME="myapp"
APP_HOME="/opt/myapp"
JAR_FILE="$APP_HOME/myapp.jar"
LOG_FILE="/var/log/myapp/app.log"
PID_FILE="$APP_HOME/app.pid"
# Check if the application is already running
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
if [ -d "/proc/$PID" ]; then
echo "$APP_NAME is already running. PID: $PID"
exit 1
else
rm $PID_FILE
fi
fi
# Start application
echo "Starting $APP_NAME..."
nohup java -jar $JAR_FILE \
--spring.profiles.active=prod \
--server.port=8080 \
> $LOG_FILE 2>&1 &
echo $! > $PID_FILE
echo "$APP_NAME started. PID: $(cat $PID_FILE)"
3.2 Stop Script
#!/bin/bash
# /opt/myapp/bin/stop.sh
APP_NAME="myapp"
PID_FILE="/opt/myapp/app.pid"
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
if [ -d "/proc/$PID" ]; then
echo "Stopping $APP_NAME. PID: $PID"
kill $PID
# Wait for application to stop
while [ -d "/proc/$PID" ]; do
sleep 1
done
rm $PID_FILE
echo "$APP_NAME stopped."
else
echo "$APP_NAME is not running."
rm $PID_FILE
fi
else
echo "$APP_NAME is not running."
fi
3.3 Restart Script
#!/bin/bash
# /opt/myapp/bin/restart.sh
APP_HOME="/opt/myapp"
$APP_HOME/bin/stop.sh
sleep 5
$APP_HOME/bin/start.sh
4. systemd Service Configuration
Create a professional systemd service file:
# /etc/systemd/system/myapp.service
[Unit]
Description=My Java Application
After=network.target
[Service]
Type=simple
User=appuser
Group=appuser
# Working directory
WorkingDirectory=/opt/myapp
# Start command
ExecStart=/usr/bin/java \
-Xms512m \
-Xmx2g \
-server \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-jar /opt/myapp/myapp.jar \
--spring.profiles.active=prod \
--server.port=8080
# Environment variables
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment=SPRING_CONFIG_LOCATION=file:/etc/myapp/
# Restart policy
Restart=always
RestartSec=10
# Log configuration
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
# Security settings
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Enable and manage the service:
# Reload systemd configuration
sudo systemctl daemon-reload
# Enable service to start on boot
sudo systemctl enable myapp.service
# Start service
sudo systemctl start myapp.service
# Check service status
sudo systemctl status myapp.service
# View service logs
sudo journalctl -u myapp.service -f
5. Best Practices for Configuration Management
5.1 Environment Variable Configuration
# /etc/myapp/environment.sh
export APP_ENV=production
export DB_HOST=localhost
export DB_PORT=3306
export DB_NAME=myapp
export DB_USER=myapp_user
export DB_PASSWORD=secure_password
export REDIS_HOST=localhost
export REDIS_PORT=6379
export LOG_LEVEL=INFO
export LOG_PATH=/var/log/myapp
5.2 Configuration File Template
# /etc/myapp/application.properties
# Database configuration
spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Redis configuration
spring.redis.host=${REDIS_HOST}
spring.redis.port=${REDIS_PORT}
# Log configuration
logging.level.root=${LOG_LEVEL}
logging.file.path=${LOG_PATH}
# Server configuration
server.port=8080
server.servlet.context-path=/
# JVM configuration (passed via startup parameters)
# -Xms512m -Xmx2g -XX:+UseG1GC
6. Monitoring and Maintenance
6.1 Application Status Monitoring
#!/bin/bash
# /opt/myapp/bin/health-check.sh
APP_URL="http://localhost:8080/actuator/health"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $APP_URL)
if [ $RESPONSE -eq 200 ]; then
echo "Application is healthy"
exit 0
else
echo "Application is unhealthy. HTTP Status: $RESPONSE"
exit 1
fi
6.2 Log Rotation Configuration
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 appuser appuser
postrotate
systemctl reload myapp > /dev/null 2>/dev/null || true
endscript
}
6.3 Performance Monitoring Script
#!/bin/bash
# /opt/myapp/bin/monitor.sh
PID_FILE="/opt/myapp/app.pid"
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
if [ -d "/proc/$PID" ]; then
# Get process information
CPU=$(ps -p $PID -o %cpu --no-headers)
MEM=$(ps -p $PID -o %mem --no-headers)
THREADS=$(ps -p $PID -o nlwp --no-headers)
echo "PID: $PID"
echo "CPU Usage: ${CPU}%"
echo "Memory Usage: ${MEM}%"
echo "Thread Count: $THREADS"
else
echo "Application is not running"
fi
else
echo "PID file not found"
fi
7. Troubleshooting
7.1 Common Startup Issues
# Check port usage
netstat -tulnp | grep :8080
lsof -i :8080
# Check disk space
df -h
# Check memory usage
free -h
# View application logs
tail -f /var/log/myapp/app.log
journalctl -u myapp.service -f
7.2 Out of Memory Issues
# Add JVM parameters for memory analysis
-Xmx2g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/myapp/
# Use jstat to monitor GC
jstat -gc <PID> 1s
# Use jmap to analyze heap memory
jmap -heap <PID>
jmap -histo <PID>
7.3 Database Connection Issues
# Test database connection
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD -e "SELECT 1;"
# Check connection pool configuration
# Look for connection pool related information in application logs
grep -i "connection\|pool" /var/log/myapp/app.log
8. Introduction to Automated Deployment
8.1 Using Shell Scripts to Simplify Deployment
#!/bin/bash
# /opt/myapp/bin/deploy.sh
APP_NAME="myapp"
APP_HOME="/opt/myapp"
BACKUP_DIR="/opt/myapp/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup current version
if [ -f "$APP_HOME/myapp.jar" ]; then
cp $APP_HOME/myapp.jar $BACKUP_DIR/myapp_$TIMESTAMP.jar
echo "Backup created: myapp_$TIMESTAMP.jar"
fi
# Stop application
$APP_HOME/bin/stop.sh
# Deploy new version
cp /tmp/myapp.jar $APP_HOME/
chown appuser:appuser $APP_HOME/myapp.jar
# Start application
$APP_HOME/bin/start.sh
# Wait for application to start
sleep 10
# Health check
$APP_HOME/bin/health-check.sh
8.2 Environment Configuration Management
#!/bin/bash
# /opt/myapp/bin/configure.sh
ENV=$1
CONFIG_DIR="/etc/myapp"
case $ENV in
"dev")
cp $CONFIG_DIR/application-dev.properties $CONFIG_DIR/application.properties
;;
"test")
cp $CONFIG_DIR/application-test.properties $CONFIG_DIR/application.properties
;;
"prod")
cp $CONFIG_DIR/application-prod.properties $CONFIG_DIR/application.properties
;;
*)
echo "Usage: $0 {dev|test|prod}"
exit 1
;;
esac
echo "Configuration switched to $ENV environment"
9. Conclusion
Deploying Java applications on Linux is a comprehensive task that involves multiple aspects. Through this article, we have learned:
- 1. Pre-deployment Preparation: Environment checks, security settings, and directory planning
- 2. Manual Deployment Process: Methods for deploying WAR and JAR packages
- 3. Script Writing: Writing startup, stop, and restart scripts
- 4. Service Management: Professional service management using systemd
- 5. Configuration Management: Best practices for environment variables and configuration files
- 6. Monitoring and Maintenance: Application status monitoring and log management
- 7. Troubleshooting: Diagnosis and solutions for common issues
- 8. Introduction to Automation: Using scripts to simplify the deployment process
In actual projects, it is recommended to:
- • Establish standardized deployment processes
- • Use configuration management tools (such as Ansible, Puppet)
- • Implement Continuous Integration/Continuous Deployment (CI/CD)
- • Establish a comprehensive monitoring and alerting mechanism
- • Regularly perform backups and disaster recovery drills
Through continuous practice and improvement, an efficient and reliable Java application deployment system can be established.