Systemd Script Guide: Designing and Creating Startup and Shutdown Scripts

Comprehensive guide with explicit details and examples for Linux system administrators. Created by Grok.

Introduction

Systemd is the default init system on most modern Linux distributions, such as Ubuntu, Fedora, and CentOS. It manages system services, daemons, and scripts during boot, runtime, and shutdown. This guide focuses on designing and creating systemd unit files for startup and shutdown scripts, providing explicit details, step-by-step instructions, and practical examples.

Startup scripts run when the system boots up, while shutdown scripts execute during system halt or reboot. Systemd uses unit files (e.g., .service) to define these behaviors.

Prerequisites: Basic Linux knowledge, root access, and a text editor like vim or nano.

Systemd Basics

Systemd organizes everything into "units." The most common for scripts is the .service unit, which can define executables to run at specific times.

Example of a minimal service unit:

[Unit]
Description=My Simple Service

[Service]
ExecStart=/path/to/my-script.sh

[Install]
WantedBy=multi-user.target
            

Designing and Creating Startup Scripts

Startup scripts are services that start automatically when the system reaches a certain target (e.g., multi-user.target for console boot or graphical.target for GUI).

Step-by-Step Design

  1. Define Purpose: What does the script do? E.g., start a web server, mount a drive, or run a backup.
  2. Choose Type: Use Type=simple for foreground processes, Type=oneshot for scripts that run once and exit.
  3. Dependencies: Use After= or Requires= to ensure order (e.g., after network).
  4. Enable at Boot: Add [Install] section with WantedBy=.
  5. Test: Reload, enable, and reboot to verify.

Example: Simple Startup Script for Logging System Info

Create a script /usr/local/bin/log-system-info.sh:

#!/bin/bash
echo "System booted at $(date)" >> /var/log/boot.log
uname -a >> /var/log/boot.log
            

Make it executable: chmod +x /usr/local/bin/log-system-info.sh

Unit file /etc/systemd/system/log-system-info.service:

[Unit]
Description=Log System Info at Startup
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/log-system-info.sh
RemainAfterExit=true

[Install]
WantedBy=multi-user.target
            

Activate: systemctl daemon-reload; systemctl enable log-system-info.service; systemctl start log-system-info.service

Advanced Example: Startup Daemon

For a persistent process like a custom server:

[Unit]
Description=My Custom Daemon
After=network-online.target

[Service]
Type=simple
ExecStart=/path/to/my-daemon --foreground
Restart=always
User=root

[Install]
WantedBy=graphical.target
            

Designing and Creating Shutdown Scripts

Shutdown scripts run before the system halts. Use services that activate during shutdown.target, often with Before=shutdown.target or ExecStop= in regular services.

Step-by-Step Design

  1. Identify Actions: E.g., save data, unmount drives, or send notifications.
  2. Use ExecStop: For services, define cleanup in ExecStop.
  3. Standalone Shutdown Unit: Use Type=oneshot with Conflicts=shutdown.target and Before=shutdown.target.
  4. Timing: Ensure it runs early using Before=umount.target or final.target.
  5. Test: Use systemctl stop <unit> or reboot.

Example: Simple Shutdown Script for Backup

Script /usr/local/bin/backup-on-shutdown.sh:

#!/bin/bash
echo "System shutting down at $(date)" >> /var/log/shutdown.log
rsync -a /important/data /backup/location
            

Make executable: chmod +x /usr/local/bin/backup-on-shutdown.sh

Unit file /etc/systemd/system/backup-on-shutdown.service:

[Unit]
Description=Backup Data on Shutdown
DefaultDependencies=no
Before=shutdown.target umount.target final.target

[Service]
Type=oneshot
ExecStart=/bin/true  # No-op for start
ExecStop=/usr/local/bin/backup-on-shutdown.sh
RemainAfterExit=true

[Install]
WantedBy=multi-user.target
            

Note: The service "starts" with a no-op but executes ExecStop on shutdown. Activate as above.

Advanced Example: Cleanup in a Running Service

For a service that needs cleanup:

[Unit]
Description=My App Service

[Service]
ExecStart=/path/to/my-app
ExecStop=/path/to/cleanup-script.sh
KillSignal=SIGTERM

[Install]
WantedBy=multi-user.target
            

Best Practices

Troubleshooting