Quick Answer:
systemctl start nginxstarts a service.systemctl enable nginxstarts it on boot.systemctl status nginxshows status.journalctl -u nginx -ffollows its logs.systemctl restart nginxrestarts it.
systemctl — Service Management
Basic Commands
# Start / Stop / Restart
systemctl start nginx
systemctl stop nginx
systemctl restart nginx # Stop then start
systemctl reload nginx # Reload config without restart (if supported)
systemctl reload-or-restart nginx
# Enable / Disable (boot behavior)
systemctl enable nginx # Start on boot
systemctl disable nginx # Don't start on boot
systemctl enable --now nginx # Enable AND start immediately
# Status
systemctl status nginx
systemctl is-active nginx # Just "active" or "inactive"
systemctl is-enabled nginx # "enabled" or "disabled"
systemctl is-failed nginx # "failed" or not
List Services
# All services
systemctl list-units --type=service
# Running services only
systemctl list-units --type=service --state=running
# Failed services
systemctl list-units --type=service --state=failed
systemctl --failed
# All installed service files
systemctl list-unit-files --type=service
# Enabled services
systemctl list-unit-files --type=service --state=enabled
Service Dependencies
# What depends on this service
systemctl list-dependencies nginx
# What this service depends on
systemctl list-dependencies nginx --reverse
# Show service properties
systemctl show nginx
systemctl show nginx -p MainPID
systemctl show nginx -p ActiveState
journalctl — Log Management
Basic Log Viewing
# All logs
journalctl
# Follow (live tail)
journalctl -f
# Specific service
journalctl -u nginx
journalctl -u nginx -f # Follow
# Last N lines
journalctl -u nginx -n 50
# Since specific time
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2026-04-06 10:00"
journalctl --since "yesterday"
journalctl --since "2 days ago" --until "1 day ago"
# Current boot only
journalctl -b
journalctl -b -1 # Previous boot
# Kernel messages
journalctl -k
journalctl -k -b # Kernel messages from current boot
Filtering and Output
# By priority (error and above)
journalctl -p err
journalctl -p warning
# Levels: emerg, alert, crit, err, warning, notice, info, debug
# Specific PID
journalctl _PID=1234
# Specific executable
journalctl _COMM=sshd
# JSON output
journalctl -u nginx -o json-pretty -n 5
# Short output (default, most readable)
journalctl -u nginx -o short-iso
# Search/grep
journalctl -u nginx | grep "error"
journalctl -u nginx -g "error|failed" # Built-in grep (systemd 245+)
Log Maintenance
# Disk usage
journalctl --disk-usage
# Clean logs older than 2 weeks
journalctl --vacuum-time=2weeks
# Clean logs to fit in 500MB
journalctl --vacuum-size=500M
# Rotate logs now
journalctl --rotate
# Permanent limits (edit /etc/systemd/journald.conf)
# SystemMaxUse=500M
# SystemMaxFileSize=50M
# MaxRetentionSec=2weeks
systemctl restart systemd-journald
Creating Custom Services
Basic Service File
Create /etc/systemd/system/myapp.service:
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Then:
systemctl daemon-reload # Load new service file
systemctl enable --now myapp # Enable and start
Service Types
| Type | Behavior |
|---|---|
simple |
Default. Process started by ExecStart is the main process |
exec |
Like simple, but systemd waits for exec() to complete |
forking |
Process forks, parent exits. Use with daemons that daemonize themselves |
oneshot |
Process exits after running. Good for scripts |
notify |
Process signals systemd when ready (requires sd_notify) |
Service with Environment Variables
[Service]
Environment=NODE_ENV=production
Environment=PORT=3000
EnvironmentFile=/opt/myapp/.env
ExecStart=/usr/bin/node /opt/myapp/server.js
Service with Logging
[Service]
ExecStart=/opt/myapp/start.sh
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
View logs: journalctl -u myapp -f
Node.js / Python App Service
# Node.js
[Unit]
Description=Node.js API
After=network.target
[Service]
Type=simple
User=node
WorkingDirectory=/opt/api
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=3
Environment=NODE_ENV=production
Environment=PORT=3000
[Install]
WantedBy=multi-user.target
# Python (with venv)
[Unit]
Description=Python Web App
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/webapp
ExecStart=/opt/webapp/venv/bin/python app.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
Docker Container as Service
[Unit]
Description=My Docker Container
After=docker.service
Requires=docker.service
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStartPre=-/usr/bin/docker stop myapp
ExecStartPre=-/usr/bin/docker rm myapp
ExecStart=/usr/bin/docker run --name myapp -p 8080:80 myimage:latest
ExecStop=/usr/bin/docker stop myapp
[Install]
WantedBy=multi-user.target
Timers (Cron Replacement)
Timer + Service Pair
Create /etc/systemd/system/backup.timer:
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=daily
# Or specific: OnCalendar=*-*-* 02:00:00 (2 AM daily)
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
Create /etc/systemd/system/backup.service:
[Unit]
Description=Run backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
systemctl daemon-reload
systemctl enable --now backup.timer
Timer Schedules
| OnCalendar | When |
|---|---|
minutely |
Every minute |
hourly |
Every hour |
daily |
Every day at midnight |
weekly |
Every Monday at midnight |
monthly |
First day of month |
--* 02:30:00 |
Daily at 2:30 AM |
Mon --* 09:00:00 |
Every Monday at 9 AM |
--01 00:00:00 |
First of every month |
*:0/15 |
Every 15 minutes |
# Validate a timer expression
systemd-analyze calendar "Mon *-*-* 09:00:00"
# List active timers
systemctl list-timers
systemctl list-timers --all
# Run timer manually (triggers the service)
systemctl start backup.service
System Commands
# Reboot
systemctl reboot
# Shutdown
systemctl poweroff
# Suspend
systemctl suspend
# Analyze boot time
systemd-analyze
systemd-analyze blame # Time per service
systemd-analyze critical-chain # Critical path
# Show system state
systemctl is-system-running
# Reload all unit files (after editing)
systemctl daemon-reload
Troubleshooting
# Service won't start? Check logs:
journalctl -u myapp -n 30 --no-pager
# Check service file syntax:
systemd-analyze verify /etc/systemd/system/myapp.service
# See full service properties:
systemctl show myapp
# Reset failed state:
systemctl reset-failed myapp
# Check what's blocking boot:
systemd-analyze critical-chain
# Emergency mode:
systemctl isolate emergency.target
# Default boot target:
systemctl get-default
systemctl set-default multi-user.target # CLI only (no GUI)
systemctl set-default graphical.target # With GUI