Systemd Units
Systemd Services#
micipsa-hardware.service#
Runs a one-shot script that validates the presence and accessibility of all required hardware peripherals (cameras and serial devices) before the rest of the stack is allowed to start. Uses RemainAfterExit=yes so that micipsa-hardware.target and micipsa-compose-stack.service can safely declare dependencies on it even after the script has exited.
[Unit]
Description=Micipsa hardware devices check
DefaultDependencies=no
After=systemd-udev-settle.service
Wants=systemd-udev-settle.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/micipsa_devices_check.sh
RemainAfterExit=yes
StandardOutput=journal
StandardError=journal
SyslogIdentifier=micipsa-hardware-check
[Install]
WantedBy=micipsa-hardware.target
Key design decisions:
DefaultDependencies=nodisables the default ordering constraints (e.g. againstshutdown.target) that are inappropriate for early-boot hardware checks.Wants=systemd-udev-settle.service(rather thanRequires) the udev settle service is a soft dependency. If it is unavailable or fails, the hardware check will still attempt to run rather than being blocked entirely.Type=oneshotwithRemainAfterExit=yesthe service is considered active as long as the check passed, even after the script process has exited. Downstream units that useAfter=micipsa-hardware.servicewill not start until the script completes successfully.
micipsa-hardware.target#
A passive synchronisation point that represents the "hardware layer is ready" state. It does not start any process itself. Other units declare WantedBy=micipsa-hardware.target or Requires=micipsa-hardware.target to hook into or depend on this layer.
[Unit]
Description=Micipsa Hardware Layer
Requires=micipsa-hardware.service
After=micipsa-hardware.service
[Install]
WantedBy=multi-user.target
Key design decisions:
Requires+Afteronmicipsa-hardware.servicethe target only becomes active once the hardware check service has completed successfully, and fails immediately if the service fails.
micipsa-compose-stack.service#
Starts the full robot software stack via the micipsa_compose wrapper, which resolves the Docker Compose configuration from the specified config directory and brings up all containers. On stop, it brings the stack down cleanly.
[Unit]
Description=Micipsa Docker Compose Stack
Documentation=https://gitlab.com/yousriouartsi-group/micipsa/micipsa
After=micipsa-hardware.target
Requires=micipsa-hardware.target
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=root
Environment=PYTHONPATH=/usr/local/lib/micipsa # to find utils files/libs
# Force-clear any leftover state from an unclean shutdown before bringing
# the stack up. The leading "-" tells systemd not to fail the unit if this
# step itself errors (e.g. nothing was running, or a container was already
# gone) it's cleanup, not a hard precondition.
ExecStartPre=-/usr/local/bin/compose_launcher down \
--docker-compose-files-dir /etc/micipsa/infra/docker/
ExecStart=/usr/local/bin/compose_launcher up \
--mode deploy \
--bringup-config-dir /etc/micipsa/micipsa_robot/micipsa_bringup/config/ \
--maps-dir /etc/micipsa/micipsa_robot/micipsa_maps/maps/ \
--dds-dir /etc/micipsa/infra/dds/ \
--bringup-config-name bringup_config.yaml \
--docker-compose-files-dir /etc/micipsa/infra/docker/
ExecStop=/usr/local/bin/compose_launcher down \
--docker-compose-files-dir /etc/micipsa/infra/docker/
Restart=on-failure
RestartSec=10s
TimeoutStartSec=120s
TimeoutStopSec=120s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=micipsa-docker
[Install]
WantedBy=multi-user.target
Key design decisions:
Requires=micipsa-hardware.targeta hard dependency. If hardware validation failed at boot, systemd will not attempt to start this service.Requires=docker.serviceensures the Docker daemon is running before anydocker composecommand is issued.Type=simpleappropriate here becausemicipsa_compose upis a long-running foreground process. systemd considers it started as soon as the process is launched.Restart=on-failurewithRestartSec=10sthe service will be restarted automatically if the compose process exits unexpectedly, but not on a clean stop (ExecStop).TimeoutStartSec=120s/TimeoutStopSec=120sallows sufficient time for Docker images to be pulled and containers to initialise on first run, and for containers to shut down gracefully on stop.
Common Command#
# Check the status of a service
sudo systemctl status <service>
# Start a service
sudo systemctl start <service>
# Stop a service
sudo systemctl stop <service>
# Restart a service
sudo systemctl restart <service>
# Enable a service (start automatically at boot)
sudo systemctl enable <service>
# Disable a service (do not start at boot)
sudo systemctl disable <service>
# Reload systemd after modifying unit files
sudo systemctl daemon-reload
