-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.sh
More file actions
executable file
·92 lines (78 loc) · 2.41 KB
/
run.sh
File metadata and controls
executable file
·92 lines (78 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env bash
set -euo pipefail
# Load defaults (USER_NAME, IMAGE_NAME, CONTAINER_NAME, SSH_PORT, PORT_START).
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "${SCRIPT_DIR}/config.env"
PORT_START="${PORT_START:-2223}"
# Return 0 if the given TCP port is LISTENing on the host, else 1.
host_port_in_use() {
local p="$1"
ss -ltn | awk '{print $4}' | grep -Eq "(^|:)${p}$"
}
# Find first available port from a given start.
find_free_port_from() {
local p="$1"
while host_port_in_use "${p}"; do
p=$((p + 1))
done
echo "${p}"
}
# True if stdin is a TTY (interactive)
is_interactive() {
[[ -t 0 ]]
}
pick_ssh_port() {
# Case 1) User did not specify SSH_PORT -> auto-pick from PORT_START
if [ -z "${SSH_PORT:-}" ]; then
find_free_port_from "${PORT_START}"
return 0
fi
# Case 2) User specified SSH_PORT -> try it
local requested="${SSH_PORT}"
if ! host_port_in_use "${requested}"; then
echo "${requested}"
return 0
fi
# Case 2.1) Requested port is busy -> ask user whether to auto-increment or exit
if ! is_interactive; then
echo "[!] ERROR: requested SSH_PORT=${requested} is already in use, but no TTY to ask." >&2
echo " - Option A: clear SSH_PORT in config.env to auto-pick" >&2
echo " - Option B: set SSH_PORT to a free port" >&2
exit 1
fi
echo "[!] Port ${requested} is already in use." >&2
local suggestion
suggestion="$(find_free_port_from "${requested}")"
echo " Next available port from ${requested} is: ${suggestion}" >&2
while true; do
read -r -p "Use ${suggestion} instead? [y/N]: " ans
case "${ans}" in
[yY]|[yY][eE][sS])
echo "${suggestion}"
return 0
;;
""|[nN]|[nN][oO])
echo "[*] Aborted by user." >&2
exit 1
;;
*)
echo "Please answer y or n." >&2
;;
esac
done
}
SELECTED_PORT="$(pick_ssh_port)"
if docker inspect "${CONTAINER_NAME}" >/dev/null 2>&1; then
docker start "${CONTAINER_NAME}" >/dev/null
echo "[*] run: started existing container=${CONTAINER_NAME} (image=${IMAGE_NAME})"
echo "[*] run: note: existing container keeps its original port mapping"
else
docker run -d \
-p "${SELECTED_PORT}:22" \
--name "${CONTAINER_NAME}" \
"${IMAGE_NAME}" >/dev/null
echo "[*] run: created container=${CONTAINER_NAME} (image=${IMAGE_NAME})"
echo "[*] run: ssh port=${SELECTED_PORT}"
fi
# EOF