Skip to content

Commit b14561f

Browse files
create a bash tool for tunnel management
1 parent de7494d commit b14561f

File tree

7 files changed

+321
-15
lines changed

7 files changed

+321
-15
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,5 @@ docker/monitoring/volumes
4949
http-client.env.json
5050

5151
src/main/resources/config/env.properties
52+
53+
tunnels/tunnels.conf

tunnels/tunnel-kafka.sh

Lines changed: 0 additions & 4 deletions
This file was deleted.

tunnels/tunnel-keycloak.sh

Lines changed: 0 additions & 3 deletions
This file was deleted.

tunnels/tunnel-mongo.sh

Lines changed: 0 additions & 4 deletions
This file was deleted.

tunnels/tunnel-zipkin.sh

Lines changed: 0 additions & 4 deletions
This file was deleted.

tunnels/tunnels.sh

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
#!/bin/bash
2+
3+
# SSH Tunnel Manager Script
4+
# Manages multiple SSH tunnels using screen sessions
5+
# Compatible with macOS default bash (3.2+)
6+
7+
# Configuration file path
8+
CONFIG_FILE="${CONFIG_FILE:-./tunnels.conf}"
9+
10+
# Load tunnel configurations from file
11+
load_config() {
12+
if [ ! -f "$CONFIG_FILE" ]; then
13+
echo -e "${RED}Error: Configuration file '$CONFIG_FILE' not found${NC}"
14+
echo -e "${YELLOW}Create a file with tunnel configurations in this format:${NC}"
15+
echo "tunnel1:2222:localhost:22:[email protected]"
16+
echo "tunnel2:3306:localhost:3306:[email protected]"
17+
echo "tunnel3:8080:localhost:80:[email protected]"
18+
echo ""
19+
echo -e "${YELLOW}You can also set a custom config file path with:${NC}"
20+
echo "export CONFIG_FILE=/path/to/your/tunnels.conf"
21+
exit 1
22+
fi
23+
24+
# Read non-empty lines that don't start with #
25+
TUNNEL_CONFIGS=()
26+
while IFS= read -r line; do
27+
# Skip empty lines and comments
28+
if [[ -n "$line" && ! "$line" =~ ^[[:space:]]*# ]]; then
29+
TUNNEL_CONFIGS+=("$line")
30+
fi
31+
done < "$CONFIG_FILE"
32+
33+
if [ ${#TUNNEL_CONFIGS[@]} -eq 0 ]; then
34+
echo -e "${RED}Error: No valid tunnel configurations found in '$CONFIG_FILE'${NC}"
35+
exit 1
36+
fi
37+
}
38+
39+
# Colors for output
40+
RED='\033[0;31m'
41+
GREEN='\033[0;32m'
42+
YELLOW='\033[1;33m'
43+
BLUE='\033[0;34m'
44+
NC='\033[0m' # No Color
45+
46+
# Function to check if screen is installed
47+
check_screen() {
48+
if ! command -v screen >/dev/null 2>&1; then
49+
echo -e "${RED}Error: screen is not installed. Install it with: brew install screen${NC}"
50+
exit 1
51+
fi
52+
}
53+
54+
# Function to parse tunnel config by name
55+
get_tunnel_config() {
56+
local name=$1
57+
for config in "${TUNNEL_CONFIGS[@]}"; do
58+
local tunnel_name=$(echo "$config" | cut -d: -f1)
59+
if [ "$tunnel_name" = "$name" ]; then
60+
echo "$config"
61+
return 0
62+
fi
63+
done
64+
return 1
65+
}
66+
67+
# Function to check if tunnel name exists
68+
tunnel_exists() {
69+
local name=$1
70+
for config in "${TUNNEL_CONFIGS[@]}"; do
71+
local tunnel_name=$(echo "$config" | cut -d: -f1)
72+
if [ "$tunnel_name" = "$name" ]; then
73+
return 0
74+
fi
75+
done
76+
return 1
77+
}
78+
79+
# Function to build SSH command from config
80+
build_ssh_command() {
81+
local config=$1
82+
local local_port=$(echo "$config" | cut -d: -f2)
83+
local remote_host=$(echo "$config" | cut -d: -f3)
84+
local remote_port=$(echo "$config" | cut -d: -f4)
85+
local ssh_server=$(echo "$config" | cut -d: -f5)
86+
87+
echo "ssh -L ${local_port}:${remote_host}:${remote_port} ${ssh_server}"
88+
}
89+
90+
# Function to start a single tunnel
91+
start_tunnel() {
92+
local name=$1
93+
local config=$(get_tunnel_config "$name")
94+
95+
if [ $? -ne 0 ]; then
96+
echo -e "${RED}Error: Tunnel '$name' not found in configuration${NC}"
97+
return 1
98+
fi
99+
100+
if screen -list | grep -q "ssh_tunnel_${name}"; then
101+
echo -e "${YELLOW}Tunnel '${name}' is already running${NC}"
102+
return 1
103+
fi
104+
105+
local ssh_cmd=$(build_ssh_command "$config")
106+
107+
echo -e "${BLUE}Starting tunnel: ${name}${NC}"
108+
echo -e "${BLUE}Command: ${ssh_cmd}${NC}"
109+
110+
# Start SSH tunnel in a detached screen session
111+
screen -dmS "ssh_tunnel_${name}" bash -c "$ssh_cmd"
112+
113+
# Give it a moment to establish
114+
sleep 2
115+
116+
# Check if the screen session is still running
117+
if screen -list | grep -q "ssh_tunnel_${name}"; then
118+
echo -e "${GREEN}✓ Tunnel '${name}' started successfully${NC}"
119+
return 0
120+
else
121+
echo -e "${RED}✗ Failed to start tunnel '${name}'${NC}"
122+
return 1
123+
fi
124+
}
125+
126+
# Function to stop a single tunnel
127+
stop_tunnel() {
128+
local name=$1
129+
130+
if ! tunnel_exists "$name"; then
131+
echo -e "${RED}Error: Tunnel '$name' not found in configuration${NC}"
132+
return 1
133+
fi
134+
135+
if ! screen -list | grep -q "ssh_tunnel_${name}"; then
136+
echo -e "${YELLOW}Tunnel '${name}' is not running${NC}"
137+
return 1
138+
fi
139+
140+
echo -e "${BLUE}Stopping tunnel: ${name}${NC}"
141+
screen -S "ssh_tunnel_${name}" -X quit
142+
143+
sleep 1
144+
145+
if ! screen -list | grep -q "ssh_tunnel_${name}"; then
146+
echo -e "${GREEN}✓ Tunnel '${name}' stopped successfully${NC}"
147+
return 0
148+
else
149+
echo -e "${RED}✗ Failed to stop tunnel '${name}'${NC}"
150+
return 1
151+
fi
152+
}
153+
154+
# Function to show tunnel status
155+
show_status() {
156+
echo -e "${BLUE}SSH Tunnel Status:${NC}"
157+
echo "===================="
158+
159+
for config in "${TUNNEL_CONFIGS[@]}"; do
160+
local name=$(echo "$config" | cut -d: -f1)
161+
if screen -list | grep -q "ssh_tunnel_${name}"; then
162+
echo -e "${name}: ${GREEN}RUNNING${NC}"
163+
else
164+
echo -e "${name}: ${RED}STOPPED${NC}"
165+
fi
166+
done
167+
168+
echo ""
169+
echo -e "${BLUE}Active screen sessions:${NC}"
170+
screen -list | grep "ssh_tunnel_" || echo "None"
171+
}
172+
173+
# Function to start all tunnels
174+
start_all() {
175+
echo -e "${BLUE}Starting all SSH tunnels...${NC}"
176+
for config in "${TUNNEL_CONFIGS[@]}"; do
177+
local name=$(echo "$config" | cut -d: -f1)
178+
start_tunnel "$name"
179+
done
180+
}
181+
182+
# Function to stop all tunnels
183+
stop_all() {
184+
echo -e "${BLUE}Stopping all SSH tunnels...${NC}"
185+
for config in "${TUNNEL_CONFIGS[@]}"; do
186+
local name=$(echo "$config" | cut -d: -f1)
187+
stop_tunnel "$name"
188+
done
189+
}
190+
191+
# Function to connect to a tunnel's screen session
192+
connect_tunnel() {
193+
local name=$1
194+
195+
if ! tunnel_exists "$name"; then
196+
echo -e "${RED}Error: Tunnel '$name' not found in configuration${NC}"
197+
return 1
198+
fi
199+
200+
if ! screen -list | grep -q "ssh_tunnel_${name}"; then
201+
echo -e "${RED}Tunnel '${name}' is not running${NC}"
202+
return 1
203+
fi
204+
205+
echo -e "${BLUE}Connecting to tunnel '${name}' screen session...${NC}"
206+
echo -e "${YELLOW}Press Ctrl+A then D to detach from the session${NC}"
207+
sleep 2
208+
screen -r "ssh_tunnel_${name}"
209+
}
210+
211+
# Function to show help
212+
show_help() {
213+
echo "SSH Tunnel Manager"
214+
echo "=================="
215+
echo "Usage: $0 [command] [tunnel_name]"
216+
echo ""
217+
echo "Commands:"
218+
echo " start [name] - Start specific tunnel or all if no name given"
219+
echo " stop [name] - Stop specific tunnel or all if no name given"
220+
echo " restart [name] - Restart specific tunnel or all if no name given"
221+
echo " status - Show status of all tunnels"
222+
echo " connect [name] - Connect to tunnel's screen session"
223+
echo " list - List available tunnel configurations"
224+
echo " help - Show this help message"
225+
echo ""
226+
echo "Available tunnels:"
227+
for config in "${TUNNEL_CONFIGS[@]}"; do
228+
local name=$(echo "$config" | cut -d: -f1)
229+
local ssh_cmd=$(build_ssh_command "$config")
230+
echo " ${name}: ${ssh_cmd}"
231+
done
232+
}
233+
234+
# Function to list available tunnels
235+
list_tunnels() {
236+
echo -e "${BLUE}Available tunnel configurations:${NC}"
237+
echo "================================"
238+
for config in "${TUNNEL_CONFIGS[@]}"; do
239+
local name=$(echo "$config" | cut -d: -f1)
240+
local ssh_cmd=$(build_ssh_command "$config")
241+
echo -e "${GREEN}${name}${NC}: ${ssh_cmd}"
242+
done
243+
}
244+
245+
# Main script logic
246+
check_screen
247+
load_config
248+
249+
case "${1:-help}" in
250+
"start")
251+
if [ -n "$2" ]; then
252+
if tunnel_exists "$2"; then
253+
start_tunnel "$2"
254+
else
255+
echo -e "${RED}Error: Tunnel '$2' not found${NC}"
256+
exit 1
257+
fi
258+
else
259+
start_all
260+
fi
261+
;;
262+
"stop")
263+
if [ -n "$2" ]; then
264+
if tunnel_exists "$2"; then
265+
stop_tunnel "$2"
266+
else
267+
echo -e "${RED}Error: Tunnel '$2' not found${NC}"
268+
exit 1
269+
fi
270+
else
271+
stop_all
272+
fi
273+
;;
274+
"restart")
275+
if [ -n "$2" ]; then
276+
if tunnel_exists "$2"; then
277+
stop_tunnel "$2"
278+
sleep 2
279+
start_tunnel "$2"
280+
else
281+
echo -e "${RED}Error: Tunnel '$2' not found${NC}"
282+
exit 1
283+
fi
284+
else
285+
stop_all
286+
sleep 3
287+
start_all
288+
fi
289+
;;
290+
"status")
291+
show_status
292+
;;
293+
"connect")
294+
if [ -n "$2" ]; then
295+
if tunnel_exists "$2"; then
296+
connect_tunnel "$2"
297+
else
298+
echo -e "${RED}Error: Tunnel '$2' not found${NC}"
299+
exit 1
300+
fi
301+
else
302+
echo -e "${RED}Error: Please specify tunnel name${NC}"
303+
show_help
304+
exit 1
305+
fi
306+
;;
307+
"list")
308+
list_tunnels
309+
;;
310+
"help"|*)
311+
show_help
312+
;;
313+
esac

tunnels/tunnels.template.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SSH Tunnel Configurations
2+
# Format: tunnel_name:local_port:remote_host:remote_port:user@ssh_server
3+
4+
tunnel1:2222:localhost:22:[email protected]
5+
tunnel2:3306:localhost:3306:[email protected]
6+
tunnel3:8080:localhost:80:[email protected]

0 commit comments

Comments
 (0)