#!/bin/bash # ============================================================================= # # Script to manage and interact with the Exwayz development container. # # Author: Gemini # Reviewer: Gemini (as Senior Developer) # # ============================================================================= # Exit immediately if a command exits with a non-zero status. set -e # --- Configuration --- readonly CONTAINER_NAME="ExwayzMapping" readonly IMAGE_NAME="beckhoff-exwayz:latest" readonly HOST_DIR="$(pwd)" # Use the current directory from where the script is run readonly CONTAINER_DIR="/app" readonly MOUNT_PATH="${HOST_DIR}:${CONTAINER_DIR}" # Default network setting. Can be overridden with --network flag. NETWORK_NAME="host" WORKING_DIR="${CONTAINER_DIR}" # --- Helper Functions --- # Displays a user-friendly usage message. usage() { cat < Specify a network name or 'host'. Defaults to 'host'. --working-dir Specify the directory inside the container to use as working directory. Defaults to the /app. --help Shows this usage message. Commands: Creates and starts the container if needed, then attaches an interactive shell. shell Explicitly creates, starts, and attaches an interactive shell. stop Stops the running container. rm Stops and removes the container. * Executes any other command inside the container (e.g., "$0 ros2 topic list"). EOF exit 1 } # Executes a command inside the running container with the ROS2 environment sourced. # $@ - The command and its arguments to execute. exec_in_container() { echo "--- Executing in container (with ROS2): '$@' ---" local ros2_setup_command=" if [ -n \"\$ROS_DISTRO\" ] && [ -f \"/opt/ros/\$ROS_DISTRO/setup.bash\" ]; then source \"/opt/ros/\$ROS_DISTRO/setup.bash\" --; echo 'Sourced ROS2 environment.' else echo 'Warning: \$ROS_DISTRO not set or setup file not found. Continuing without sourcing ROS2 environment.' >&2 fi; exec \"\$@\" " podman exec -it -w "${WORKING_DIR}" "${CONTAINER_NAME}" \ /bin/bash -c "${ros2_setup_command}" bash "$@" } # --- Argument Parsing --- # Parse flags like --network before handling commands. while [[ $# -gt 0 ]]; do case "$1" in --network) if [[ -z "$2" ]]; then echo "Error: --network requires a name." >&2 exit 1 fi NETWORK_NAME="$2" shift # remove --network shift # remove its value ;; --working-dir) if [[ -z "$2" ]]; then echo "Error: --working-dir requires a path." >&2 exit 1 fi WORKING_DIR="$2" shift # remove --working-dir shift # remove its value ;; --help) usage ;; *) # Not a flag we recognize, so it must be the start of the command. break ;; esac done # --- Main Logic --- # Handle stateless commands that don't require the container to be running. case "$1" in stop) echo "Stopping container '${CONTAINER_NAME}'..." podman stop "${CONTAINER_NAME}" exit 0 ;; rm) echo "Stopping and removing container '${CONTAINER_NAME}'..." # Stop container, ignoring errors if it's already stopped. podman stop "${CONTAINER_NAME}" >/dev/null 2>&1 || true podman rm "${CONTAINER_NAME}" exit 0 ;; esac # --- Container Lifecycle Management --- # For all other commands, ensure the container is running. # Check if a container with the specified name already exists. if ! podman ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}"$; then echo "Container '${CONTAINER_NAME}' not found. Creating and starting a new one..." podman run -d --name "${CONTAINER_NAME}" \ --network="${NETWORK_NAME}" \ --ipc=host \ --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ -v "${MOUNT_PATH}" \ -w "${CONTAINER_DIR}" \ "${IMAGE_NAME}" \ tail -f /dev/null # Keep container running echo "Container created and started." # If the container exists, check if it is running. elif ! podman ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}"$; then echo "Container '${CONTAINER_NAME}' exists but is stopped. Starting it..." podman start "${CONTAINER_NAME}" echo "Container started." else echo "Container '${CONTAINER_NAME}' is already running." fi # --- Command Execution --- # Decide what to execute inside the container. case "$1" in "" | "shell") # No arguments or "shell" argument exec_in_container /bin/bash ;; *) exec_in_container "$@" ;; esac echo "Script finished."