Processes and systemd

Introduction

Every running program is a process with a PID. On modern Linux, systemd starts services at boot, restarts failed daemons, and collects logs. This chapter shows how to inspect processes, run background jobs, manage units like Nginx or MySQL, and schedule tasks with cron.

Prerequisites

View Processes

bash
# Snapshot of all processes
ps aux | head
 
# Filter by name
ps aux | grep nginx
 
# PID of a program
pgrep nginx
pidof nginx

Interactive monitor:

bash
# Install if needed
sudo apt install -y htop
htop

Press q to quit top/htop.

Key columns in ps aux:

ColumnMeaning
USEROwner
PIDProcess ID
%CPU / %MEMResource use
COMMANDProgram

Foreground, Background, nohup

bash
# Run in background
sleep 300 &
 
# List jobs in this shell
jobs
 
# Bring job 1 to foreground
fg %1

Survive SSH disconnect with nohup:

bash
# Output to nohup.out in current directory
nohup java -jar app.jar > app.log 2>&1 &
 
# Note PID
echo $!

Production prefers systemd over raw nohup—reliable restart and logging.

Signals and kill

bash
# Graceful stop (SIGTERM)
kill 12345
 
# Force kill (SIGKILL) — last resort
kill -9 12345
 
# Kill by name
pkill nginx

Warning

kill -9 does not allow cleanup—databases and JVMs may corrupt data. Try graceful stop first.

systemd Basics

systemd manages units. Common type: service (.service).

bash
# List running services
systemctl list-units --type=service --state=running | head
 
# Status of ssh
systemctl status ssh
 
# Status of nginx after install
systemctl status nginx

Control services:

bash
# Start / stop / restart
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
 
# Enable at boot / disable
sudo systemctl enable nginx
sudo systemctl disable nginx

Reload config without full restart (when supported):

bash
sudo systemctl reload nginx

Service Logs with journalctl

bash
# Follow ssh service log
sudo journalctl -u ssh -f
 
# Last 100 nginx log lines
sudo journalctl -u nginx -n 100 --no-pager
 
# Since today
sudo journalctl -u nginx --since today

Apps logging to files still use tail -f /path/to/app.log—many Java/Node apps write their own files under /var/log or /opt/myapp/logs.

Example: Run Spring Boot as a systemd Service

Create user and directory (if not exists):

bash
sudo useradd -r -s /bin/false myapp || true
sudo mkdir -p /opt/myapp
sudo chown myapp:myapp /opt/myapp

Place app.jar in /opt/myapp/. Unit file /etc/systemd/system/myapp.service:

Enable and start:

bash
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp
sudo journalctl -u myapp -f

Adjust JAVA_HOME or JVM flags in ExecStart as needed.

Node with PM2 (Alternative)

Node teams often use PM2 instead of hand-written units—see deployment notes in project README. systemd remains the OS-level standard for Nginx, MySQL, and system daemons.

cron Scheduled Tasks

Edit crontab for current user:

bash
crontab -e

Example entries:

cron
# m h dom mon dow command
# Daily backup at 2:30 AM
30 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
 
# Every 5 minutes health check
*/5 * * * * curl -sf http://127.0.0.1:8080/health || echo "down" >> /tmp/health.log

List and logs:

bash
crontab -l
grep CRON /var/log/syslog | tail

Use systemd timers for complex scheduling on modern distros—cron remains ubiquitous and easy.

Mini Example: Install and Control Nginx

bash
sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
curl -I http://127.0.0.1/
sudo systemctl status nginx

FAQ

zombie processes?

Parent should reap children; zombies often mean buggy parent—investigate with ps aux | grep Z.

Port already in use?

sudo ss -tlnp | grep :8080 finds PID; stop conflicting service.

Changed unit file but behavior old?

sudo systemctl daemon-reload after editing .service files.

Java process disappears after SSH exit?

You started without nohup/systemd—use a service unit for production.

What comes next?

Disk usage and archives.