157 lines
4.9 KiB
Bash
157 lines
4.9 KiB
Bash
#!/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 <<EOF
|
|
Usage: $0 [options] [command] [args...]
|
|
|
|
Manages the Exwayz container lifecycle and provides an execution environment.
|
|
|
|
Options:
|
|
--network <name> Specify a network name or 'host'. Defaults to 'host'.
|
|
--working-dir <path> Specify the directory inside the container to use as working directory. Defaults to the /app.
|
|
--help Shows this usage message.
|
|
|
|
Commands:
|
|
<none> 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." |