Introduction to Systemd
Systemd is a system and service manager for Linux operating systems. It's the first process started during boot (PID 1) and manages all other processes and services.
Creating systemd services allows you to:
- Automatically start applications during system boot
- Manage application lifecycle (start, stop, restart)
- Define dependencies between services
- Configure resource limits and security settings
- Set up proper logging and monitoring
Note: This guide assumes you're working on a Linux system with systemd installed. Most modern distributions (Ubuntu 15.04+, Debian 8+, CentOS 7+, etc.) use systemd by default.
Understanding Systemd Service Files
Systemd services are defined using .service files, which are plain text configuration files with a specific structure.
Service File Locations
- /usr/lib/systemd/system/ - System-provided service files
- /etc/systemd/system/ - System administrator-created service files (preferred location)
- ~/.config/systemd/user/ - User-specific service files
Basic Service File Structure
[Unit]
Description=Service description
After=network.target
[Service]
Type=simple
ExecStart=/path/to/startup/script
ExecStop=/path/to/shutdown/script
User=username
Group=groupname
Restart=on-failure
[Install]
WantedBy=multi-user.target
Common [Unit] Section Directives
| Directive | Description |
|---|---|
| Description | Human-readable description of the service |
| After | Specifies services that should be started before this service |
| Before | Specifies services that should be started after this service |
| Requires | Other services that must be started for this service to run |
| Wants | Other services that should be started but aren't required |
Common [Service] Section Directives
| Directive | Description |
|---|---|
| Type | Service type (simple, forking, oneshot, dbus, notify) |
| ExecStart | Command to start the service |
| ExecStop | Command to stop the service |
| ExecReload | Command to reload the service |
| User | User account to run the service as |
| Group | Group to run the service as |
| WorkingDirectory | Working directory for the service |
| Restart | When to restart the service (no, on-success, on-failure, always) |
Creating a Startup Script
A startup script initializes your application or service when the system boots or when the service is manually started.
1. Create the Script
Create a shell script that will start your application. Make sure it's executable.
#!/bin/bash
# Example startup script for a web application
echo "Starting MyWebApp at $(date)" >> /var/log/mywebapp.log
# Change to application directory
cd /opt/mywebapp
# Start the application
./bin/mywebapp start
# If the application runs in the foreground, you might need to use:
# exec ./bin/mywebapp
2. Make the Script Executable
Set the proper permissions for your script:
chmod +x /path/to/your/startup-script.sh
3. Test the Script
Run the script manually to ensure it works correctly:
sudo /path/to/your/startup-script.sh
Important: For services that run in the foreground (Type=simple), the script should not exit until the service stops. For background services (Type=forking), the script should fork and then exit.
Creating a Shutdown Script
A shutdown script properly stops your application when the system shuts down or when the service is stopped.
1. Create the Script
Create a shell script that will gracefully stop your application.
#!/bin/bash
# Example shutdown script for a web application
echo "Stopping MyWebApp at $(date)" >> /var/log/mywebapp.log
# Change to application directory
cd /opt/mywebapp
# Stop the application gracefully
./bin/mywebapp stop
# If the application needs a force kill after a timeout:
# timeout 30s ./bin/mywebapp stop
# if [ $? -ne 0 ]; then
# pkill -f mywebapp
# fi
2. Make the Script Executable
Set the proper permissions:
chmod +x /path/to/your/shutdown-script.sh
3. Test the Script
Run the script manually to ensure it stops your application correctly:
sudo /path/to/your/shutdown-script.sh
Tip: Your shutdown script should handle both graceful shutdown and force termination if necessary. Always try to stop the application gracefully first, then use force methods if it doesn't respond within a reasonable time.
Complete Example: Web Application Service
Let's create a complete example for a hypothetical web application called "MyWebApp".
1. Create the Service File
Create the file at /etc/systemd/system/mywebapp.service:
[Unit]
Description=MyWebApp Service
After=network.target
Wants=network.target
[Service]
Type=simple
User=webapp
Group=webapp
WorkingDirectory=/opt/mywebapp
ExecStart=/opt/mywebapp/scripts/start.sh
ExecStop=/opt/mywebapp/scripts/stop.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
# Security settings
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/mywebapp/logs /opt/mywebapp/data
[Install]
WantedBy=multi-user.target
2. Create the Startup Script
Create /opt/mywebapp/scripts/start.sh:
#!/bin/bash
# MyWebApp Startup Script
echo "$(date): Starting MyWebApp" >> /opt/mywebapp/logs/service.log
# Check if required directories exist
mkdir -p /opt/mywebapp/logs
mkdir -p /opt/mywebapp/data
# Start the application
exec /opt/mywebapp/bin/mywebapp \
--config /opt/mywebapp/config/app.conf \
--logfile /opt/mywebapp/logs/app.log \
--pidfile /opt/mywebapp/data/app.pid
3. Create the Shutdown Script
Create /opt/mywebapp/scripts/stop.sh:
#!/bin/bash
# MyWebApp Shutdown Script
echo "$(date): Stopping MyWebApp" >> /opt/mywebapp/logs/service.log
# Try graceful shutdown first
if [ -f /opt/mywebapp/data/app.pid ]; then
PID=$(cat /opt/mywebapp/data/app.pid)
kill -TERM $PID
# Wait for process to exit
for i in {1..30}; do
if ! kill -0 $PID 2>/dev/null; then
echo "MyWebApp stopped gracefully" >> /opt/mywebapp/logs/service.log
exit 0
fi
sleep 1
done
# Force kill if still running
echo "MyWebApp did not stop gracefully, forcing kill" >> /opt/mywebapp/logs/service.log
kill -KILL $PID
fi
# Fallback: kill by process name if PID file doesn't exist
pkill -f "mywebapp"
4. Set Permissions
# Make scripts executable
chmod +x /opt/mywebapp/scripts/start.sh
chmod +x /opt/mywebapp/scripts/stop.sh
# Create the webapp user and set ownership
sudo useradd -r -s /bin/false webapp
sudo chown -R webapp:webapp /opt/mywebapp
Managing Systemd Services
Once you've created your service file and scripts, you need to enable and manage the service.
Reload Systemd
After creating or modifying a service file, reload systemd to recognize the changes:
sudo systemctl daemon-reload
Enable the Service
Enable the service to start automatically at boot:
sudo systemctl enable mywebapp.service
Start the Service
Start the service immediately:
sudo systemctl start mywebapp.service
Check Service Status
Verify the service is running correctly:
sudo systemctl status mywebapp.service
Stop the Service
Stop the service:
sudo systemctl stop mywebapp.service
Restart the Service
Restart the service:
sudo systemctl restart mywebapp.service
View Service Logs
Check the service logs using journalctl:
sudo journalctl -u mywebapp.service -f
Disable the Service
Prevent the service from starting at boot:
sudo systemctl disable mywebapp.service
Success: You've now created a complete systemd service with proper startup and shutdown scripts! Your application will now start automatically on system boot and stop gracefully on system shutdown.