Production Java processes should normally be managed by systemd, a container orchestrator, or another supervisor. Searching ps output and killing a matched PID is fragile: it can select the grep process, match multiple applications, or start a duplicate instance.
Recommended: a systemd service
Create /etc/systemd/system/myapp.service:
1 | [Unit] |
Create a non-login service user, make application files readable but not writable by unrelated users, and keep secrets in a restricted environment file or secrets manager.
Load and use the service:
1 | sudo systemctl daemon-reload |
Systemd tracks the actual process, serializes lifecycle operations, captures logs, and can restart failures.
Graceful shutdown
A normal systemctl stop sends SIGTERM. The application should stop accepting traffic, finish or reject in-flight work, close database connections, and exit before TimeoutStopSec. Spring Boot handles SIGTERM gracefully when its shutdown settings and surrounding infrastructure are configured correctly.
Do not use kill -9 as the first action. SIGKILL prevents cleanup and can leave partial work or stale locks. Reserve it for a process that does not exit after the documented grace period.
Health verification
A process being alive does not mean it is ready. After restart, check a readiness endpoint:
1 | for attempt in {1..30}; do |
Load balancers should remove the instance before shutdown and add it back only after readiness succeeds.
Shell-script fallback
If systemd is unavailable, use a PID file created when the process starts:
1 |
|
Add locking if concurrent executions are possible, rotate logs, and verify startup health. This fallback is still less reliable than a supervisor, so migrate to systemd or an orchestrator when possible.
