How to Fix an Error When Running a Spring Boot Web App as a Service in Linux

While deploying a client Spring Boot web app as a Linux service, I ran into the Exec format error caused by a missing #!/bin/bash line in the startup script. Once I added the shebang, removed unnecessary sudo, and ensured the script was executable, the service started cleanly. I then enhanced it for production by adding logging, a JAR existence check, JVM memory settings, and automatic restarts. Now the service is more reliable, easier to debug, and resilient against failures.

springboot.service: Failed to execute command: Exec format error
springboot.service: Failed at step EXEC spawning /home/ubuntu/spring-start.sh: Exec format error

I recently hit this exact issue while deploying my Spring Boot web app as a Linux service.
At first, it was frustrating because the error wasn’t very descriptive but once I figured it out, it turned out to be a very simple fix.
Let me walk you through my original code, why it failed, and how I improved it for production use.

Original Service File and Script

Here’s what I started with.

springboot.service

[Unit]
Description=My Webapp Java REST Service

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu

# Bash script to start the Spring Boot JAR
ExecStart=/home/ubuntu/spring-start.sh

SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

spring-start.sh

sudo java -jar "/home/ubuntu/FirstWebAppWithoutDB.jar"

Setup Commands

chmod u+x spring-start.sh
sudo systemctl daemon-reload
sudo systemctl enable springboot.service
sudo systemctl start springboot
sudo systemctl status springboot

Why I Got the Exec format error

After running systemctl start springboot, I was greeted with:

springboot.service: Failed to execute command: Exec format error
springboot.service: Failed at step EXEC spawning /home/ubuntu/spring-start.sh: Exec format error

The cause? My script was missing the shebang line.

Linux didn’t know what program should interpret the script. When you run something from the terminal manually, your shell interprets it automatically, but systemd needs explicit instructions.

The Fix Code

I fixed it by adding the shebang at the very top of the script and making a couple of other adjustments.

spring-start.sh (fixed)

#!/bin/bash
java -jar "/home/ubuntu/FirstWebAppWithoutDB.jar"

Key fixes:

  • Added #!/bin/bash — tells Linux to use Bash to execute the file.
  • Removed sudo — systemd already runs this under User=ubuntu.
  • Double-checked execution permissions:
chmod +x /home/ubuntu/spring-start.sh

Adding More Practical Functionality

Once I got it working, I decided to make it production-friendly.
Here’s what I added:

  • Logging output so I can check startup errors later.
  • File existence check to avoid silent failures.
  • JVM memory options for better performance.
  • Graceful error handling for a cleaner exit.

spring-start.sh (improved)

#!/bin/bash
APP_PATH="/home/ubuntu/FirstWebAppWithoutDB.jar"
LOG_FILE="/home/ubuntu/springboot.log"

# Check if JAR exists
if [[ ! -f "$APP_PATH" ]]; then
  echo "$(date) - ERROR: JAR file not found at $APP_PATH" >> "$LOG_FILE"
  exit 1
fi

echo "$(date) - Starting Spring Boot application..." >> "$LOG_FILE"

# Run the application with JVM options
exec java -Xms512m -Xmx1024m -jar "$APP_PATH" >> "$LOG_FILE" 2>&1

Updated Service File for Logging

I also updated my service file so that systemd sends logs directly to my application log file.

springboot.service (updated)

[Unit]
Description=My Webapp Java REST Service
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu
ExecStart=/home/ubuntu/spring-start.sh
StandardOutput=append:/home/ubuntu/springboot.log
StandardError=append:/home/ubuntu/springboot.log
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Final Thought

A missing #!/bin/bash line caused me hours of frustration, but fixing it not only solved the Exec format error it also pushed me to improve my Spring Boot service. Now it starts cleanly, logs for easier debugging, checks for missing JAR files, and restarts automatically if something goes wrong.

Related blog posts