|
1 | | -ORIG_INPUT_PARAMS="$@" |
2 | | -params="$(getopt -o d:n: -l directory: -l name:,with-cuda,with-ros,noble,arm64 --name "$(basename "$0")" -- "$@")" |
| 1 | +#!/usr/bin/env bash |
3 | 2 |
|
4 | | -if [ $? -ne 0 ] |
5 | | -then |
6 | | - echo "Parameter error" |
7 | | - print_usage |
8 | | -fi |
| 3 | +# Exit immediately if a command exits with a non-zero status, |
| 4 | +# treat unset variables as errors, and ensure pipelines fail correctly. |
| 5 | +set -euo pipefail |
| 6 | + |
| 7 | +# ---------------------------- |
| 8 | +# Color Definitions |
| 9 | +# ---------------------------- |
| 10 | +RED='\033[0;31m' # Red |
| 11 | +GREEN='\033[0;32m' # Green |
| 12 | +YELLOW='\033[0;33m' # Yellow |
| 13 | +NC='\033[0m' # No Color |
9 | 14 |
|
| 15 | +# ---------------------------- |
| 16 | +# Function Definitions |
| 17 | +# ---------------------------- |
| 18 | + |
| 19 | +# Function to display usage information |
10 | 20 | print_usage() { |
11 | | - printf "bash $0 [-d|--directory <workspace directory>] [--with-cuda] [--with-ros] [--noble] [--arm64] [-n|--name <container name>]\n" |
| 21 | + cat <<EOF |
| 22 | +Usage: bash $(basename "$0") [OPTIONS] |
| 23 | +
|
| 24 | +Options: |
| 25 | + -d, --directory <workspace directory> Specify the workspace directory. |
| 26 | + -n, --name <container name> Specify the container name. |
| 27 | +
|
| 28 | + --with-cuda Use CUDA-enabled image. |
| 29 | + --with-ros Include ROS in the image. |
| 30 | + --noble Use 'noble' tag (Ubuntu 24.04). |
| 31 | + --arm64 Use ARM64 architecture image. |
| 32 | +
|
| 33 | + -h, --help Show this help message and exit. |
| 34 | +
|
| 35 | +Examples: |
| 36 | + bash $(basename "$0") -d \${CoverageControl_ws} --with-cuda --with-ros |
| 37 | + bash $(basename "$0") --noble --arm64 -n my_container |
| 38 | +
|
| 39 | +Note: |
| 40 | + - If no directory is specified, the container will not mount any volume. |
| 41 | + - By default, the script uses the 'jammy' (Ubuntu 22.04) tag. |
| 42 | +EOF |
12 | 43 | } |
13 | 44 |
|
14 | | -eval set -- "$params" |
15 | | -unset params |
| 45 | +# Function to check if a command exists |
| 46 | +command_exists() { |
| 47 | + command -v "$1" >/dev/null 2>&1 |
| 48 | +} |
16 | 49 |
|
17 | | -IMAGE_BASE_NAME=agarwalsaurav/pytorch_base |
18 | | -IMAGE_TAG=latest |
| 50 | +# Function to handle errors with colored output |
| 51 | +error_exit() { |
| 52 | + echo -e "${RED}Error: $1${NC}" >&2 |
| 53 | + exit 1 |
| 54 | +} |
19 | 55 |
|
20 | | -NOBLE=false |
21 | | -while true; do |
22 | | - case ${1} in |
23 | | - -d|--directory) WS_DIR=("${2}");shift 2;; |
24 | | - -n|--name) CONTAINER_NAME=("${2}");shift 2;; |
25 | | - --with-cuda) CUDA_IMAGE=true;shift;; |
26 | | - --with-ros) ROS_IMAGE=true;shift;; |
27 | | - --noble) NOBLE=true;shift;; |
28 | | - --arm64) ARM=true;shift;; |
29 | | - --) shift;break;; |
30 | | - *) print_usage |
31 | | - exit 1 ;; |
32 | | - esac |
| 56 | +# Function to display informational messages |
| 57 | +info_message() { |
| 58 | + echo -e "${GREEN}$1${NC}" |
| 59 | +} |
| 60 | + |
| 61 | +# Function to display warnings |
| 62 | +warning_message() { |
| 63 | + echo -e "${YELLOW}Warning: $1${NC}" |
| 64 | +} |
| 65 | + |
| 66 | +# Ensure required commands are available |
| 67 | +for cmd in docker getopt; do |
| 68 | + if ! command_exists "$cmd"; then |
| 69 | + error_exit "'$cmd' command is not found. Please install it before running this script." |
| 70 | + fi |
33 | 71 | done |
34 | 72 |
|
| 73 | +if [[ $# -eq 0 ]]; then |
| 74 | + print_usage |
| 75 | + exit 1 |
| 76 | +fi |
| 77 | + |
| 78 | +# Save original input parameters |
| 79 | +ORIG_INPUT_PARAMS="$@" |
| 80 | + |
| 81 | +# Define short and long options |
| 82 | +SHORT_OPTS="d:n:h" |
| 83 | +LONG_OPTS="directory:,name:,with-cuda,with-ros,noble,arm64,help" |
| 84 | + |
| 85 | +# Parse options using getopt |
| 86 | +PARSED_PARAMS=$(getopt -o "$SHORT_OPTS" -l "$LONG_OPTS" --name "$(basename "$0")" -- "$@") || { |
| 87 | + error_exit "Failed to parse arguments." |
| 88 | +} |
| 89 | + |
| 90 | +# Evaluate the parsed options |
| 91 | +eval set -- "$PARSED_PARAMS" |
| 92 | + |
| 93 | +# Initialize variables with default values |
| 94 | +WS_DIR="" |
| 95 | +CONTAINER_NAME="" |
| 96 | +CUDA_IMAGE=false |
| 97 | +ROS_IMAGE=false |
| 98 | +NOBLE=false |
| 99 | +ARM=false |
| 100 | + |
| 101 | +IMAGE_BASE_NAME="agarwalsaurav/pytorch_base" |
| 102 | +IMAGE_TAG="latest" |
| 103 | +CONTAINER_OPTIONS="" |
35 | 104 | CONTAINER_CC_WS="/workspace" |
36 | 105 |
|
37 | | -if [ -z ${WS_DIR} ]; then |
38 | | - VOLUME_OPTION="" |
39 | | -else |
40 | | - VOLUME_OPTION="-v ${WS_DIR}:${CONTAINER_CC_WS}:rw" |
41 | | -fi |
| 106 | +# Process parsed options |
| 107 | +while true; do |
| 108 | + case "$1" in |
| 109 | + -d|--directory) |
| 110 | + WS_DIR="$2" |
| 111 | + shift 2 |
| 112 | + ;; |
| 113 | + -n|--name) |
| 114 | + CONTAINER_NAME="$2" |
| 115 | + shift 2 |
| 116 | + ;; |
| 117 | + --with-cuda) |
| 118 | + CUDA_IMAGE=true |
| 119 | + shift |
| 120 | + ;; |
| 121 | + --with-ros) |
| 122 | + ROS_IMAGE=true |
| 123 | + shift |
| 124 | + ;; |
| 125 | + --noble) |
| 126 | + NOBLE=true |
| 127 | + shift |
| 128 | + ;; |
| 129 | + --arm64) |
| 130 | + ARM=true |
| 131 | + shift |
| 132 | + ;; |
| 133 | + -h|--help) |
| 134 | + print_usage |
| 135 | + exit 0 |
| 136 | + ;; |
| 137 | + --) |
| 138 | + shift |
| 139 | + break |
| 140 | + ;; |
| 141 | + *) |
| 142 | + error_exit "Unknown option: $1" |
| 143 | + ;; |
| 144 | + esac |
| 145 | +done |
| 146 | + |
| 147 | +# ---------------------------- |
| 148 | +# Configuration |
| 149 | +# ---------------------------- |
42 | 150 |
|
43 | | -if [[ ${NOBLE} == true ]]; then |
| 151 | +# Set the base image tag based on options |
| 152 | +if [[ "$NOBLE" == true ]]; then |
44 | 153 | IMAGE_TAG="noble" |
45 | 154 | else |
46 | 155 | IMAGE_TAG="jammy" |
47 | 156 | fi |
48 | 157 |
|
49 | | -IMAGE_TAG=${IMAGE_TAG}-torch2.5.1 |
| 158 | +IMAGE_TAG="${IMAGE_TAG}-torch2.5.1" |
50 | 159 |
|
51 | | -if [[ ${CUDA_IMAGE} == true ]]; then |
52 | | - CONTAINER_OPTIONS+="--gpus all " |
53 | | - if [[ ${NOBLE} == true ]]; then |
| 160 | +# Handle CUDA options |
| 161 | +if [[ "$CUDA_IMAGE" == true ]]; then |
| 162 | + CONTAINER_OPTIONS+="--gpus all " |
| 163 | + if [[ "$NOBLE" == true ]]; then |
54 | 164 | IMAGE_TAG="${IMAGE_TAG}-cuda12.6.2" |
55 | 165 | else |
56 | 166 | IMAGE_TAG="${IMAGE_TAG}-cuda12.4.1" |
57 | 167 | fi |
58 | 168 | fi |
59 | 169 |
|
60 | | -if [[ ${ROS_IMAGE} == true ]]; then |
61 | | - if [[ ${NOBLE} == true ]]; then |
| 170 | +# Handle ROS options |
| 171 | +if [[ "$ROS_IMAGE" == true ]]; then |
| 172 | + if [[ "$NOBLE" == true ]]; then |
62 | 173 | IMAGE_TAG="${IMAGE_TAG}-jazzy" |
63 | 174 | else |
64 | 175 | IMAGE_TAG="${IMAGE_TAG}-humble" |
65 | 176 | fi |
66 | 177 | fi |
67 | 178 |
|
68 | | -if [[ ${ARM} == true ]]; then |
69 | | - if [[ ${NOBLE} == true ]]; then |
| 179 | +# Handle ARM64 architecture |
| 180 | +if [[ "$ARM" == true ]]; then |
| 181 | + if [[ "$NOBLE" == true ]]; then |
70 | 182 | IMAGE_TAG="arm64-noble-torch2.5.1-jazzy" |
71 | 183 | else |
72 | 184 | IMAGE_TAG="arm64-jammy-torch2.5.1-humble" |
73 | 185 | fi |
74 | 186 | fi |
75 | 187 |
|
76 | 188 | IMAGE_NAME="${IMAGE_BASE_NAME}:${IMAGE_TAG}" |
77 | | -docker pull ${IMAGE_NAME} |
78 | 189 |
|
79 | | -if [ -z ${CONTAINER_NAME} ]; then |
80 | | - CONTAINER_NAME="coverage-control-${USER}" |
| 190 | +# Pull the Docker image |
| 191 | +info_message "Pulling Docker image: ${IMAGE_NAME}" |
| 192 | +if ! docker pull "${IMAGE_NAME}"; then |
| 193 | + error_exit "Failed to pull Docker image: ${IMAGE_NAME}" |
| 194 | +fi |
| 195 | + |
| 196 | +# Set container name if not provided |
| 197 | +if [[ -z "$CONTAINER_NAME" ]]; then |
| 198 | + CONTAINER_NAME="coverage-control-${USER}" |
| 199 | +fi |
| 200 | + |
| 201 | +# Set volume option if workspace directory is provided |
| 202 | +if [[ -n "$WS_DIR" ]]; then |
| 203 | + if [[ ! -d "$WS_DIR" ]]; then |
| 204 | + error_exit "Workspace directory '$WS_DIR' does not exist." |
| 205 | + fi |
| 206 | + VOLUME_OPTION="-v ${WS_DIR}:${CONTAINER_CC_WS}:rw" |
| 207 | +else |
| 208 | + VOLUME_OPTION="" |
81 | 209 | fi |
82 | 210 |
|
83 | | -docker run -it \ |
84 | | - --name=${CONTAINER_NAME} \ |
85 | | - ${CONTAINER_OPTIONS} \ |
86 | | - --env=CoverageControl_ws=${CONTAINER_CC_WS} \ |
87 | | - --net=host \ |
88 | | - --privileged \ |
89 | | - --ipc=host \ |
90 | | - ${VOLUME_OPTION} \ |
91 | | - --workdir=${CONTAINER_CC_WS} \ |
92 | | - ${IMAGE_NAME} \ |
93 | | - bash |
| 211 | +# ---------------------------- |
| 212 | +# Docker Run Command |
| 213 | +# ---------------------------- |
| 214 | + |
| 215 | +docker run -it --init \ |
| 216 | + --name="${CONTAINER_NAME}" \ |
| 217 | + ${CONTAINER_OPTIONS} \ |
| 218 | + --env=CoverageControl_ws="${CONTAINER_CC_WS}" \ |
| 219 | + --net=host \ |
| 220 | + --privileged \ |
| 221 | + --ipc=host \ |
| 222 | + ${VOLUME_OPTION} \ |
| 223 | + --workdir="${CONTAINER_CC_WS}" \ |
| 224 | + "${IMAGE_NAME}" \ |
| 225 | + bash |
| 226 | + |
0 commit comments