Skip to content

Commit b72aa5d

Browse files
committed
Add remote port availability validation
Check if backend port is already in use on remote server during deployment: - Add check_remote_port_available() to validation.sh Uses ss, netstat, or tcp fallback to detect listening ports - Add suggest_available_port() to validation.sh Suggests ports 3000-3010, then 8080-8099, then random ephemeral - Update deploy_backend() to warn if port is in use Shows suggested port and command to check existing listeners - Helps prevent port conflicts when deploying multiple apps
1 parent f913d33 commit b72aa5d

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

lib/commands/deploy.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ deploy_backend() {
3232
# Verify package manager is installed on remote server
3333
verify_remote_pkg_manager "$PKG_MANAGER"
3434

35+
# Check if port is available on the server
36+
if ! check_remote_port_available "$BACKEND_PORT"; then
37+
local suggested_port
38+
suggested_port=$(suggest_available_port "$BACKEND_PORT")
39+
warn "Port $BACKEND_PORT is already in use on $SSH_HOST"
40+
warn "Consider updating shipnode.conf: BACKEND_PORT=$suggested_port"
41+
warn "Or check running apps with: ssh $SSH_USER@$SSH_HOST -p $SSH_PORT 'ss -tln | grep LISTEN'"
42+
fi
43+
3544
if [ "$ZERO_DOWNTIME" = "true" ]; then
3645
deploy_backend_zero_downtime
3746
else

lib/validation.sh

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,84 @@ test_ssh_connection() {
121121
return 1
122122
}
123123

124+
# Check if a port is available on the remote server
125+
# Returns: 0 if available, 1 if in use
126+
# Args:
127+
# $1: Port number to check
128+
# $2: SSH user (optional, uses SSH_USER if not provided)
129+
# $3: SSH host (optional, uses SSH_HOST if not provided)
130+
# $4: SSH port (optional, uses SSH_PORT if not provided)
131+
check_remote_port_available() {
132+
local port=$1
133+
local user=${2:-$SSH_USER}
134+
local host=${3:-$SSH_HOST}
135+
local ssh_port=${4:-$SSH_PORT}
136+
137+
if [ -z "$port" ] || [ -z "$user" ] || [ -z "$host" ]; then
138+
return 1
139+
fi
140+
141+
# Check if anything is listening on the port
142+
local result
143+
result=$(ssh -o ConnectTimeout=5 -p "$ssh_port" "$user@$host" "
144+
if command -v ss >/dev/null 2>&1; then
145+
ss -tln | grep -q \":$port \"
146+
elif command -v netstat >/dev/null 2>&1; then
147+
netstat -tln 2>/dev/null | grep -q \":$port \"
148+
else
149+
# Fallback: try to connect to the port
150+
timeout 1 bash -c \"exec 3<>/dev/tcp/127.0.0.1/$port\" 2>/dev/null
151+
fi
152+
echo \$?
153+
" 2>/dev/null)
154+
155+
# If result is 0, port is in use
156+
if [ "$result" = "0" ]; then
157+
return 1 # Port is NOT available
158+
fi
159+
160+
return 0 # Port is available
161+
}
162+
163+
# Suggest an available port on the remote server
164+
# Tries ports in range 3000-3010, then falls back to random high port
165+
# Args:
166+
# $1: Preferred port (optional)
167+
# $2: SSH user (optional, uses SSH_USER if not provided)
168+
# $3: SSH host (optional, uses SSH_HOST if not provided)
169+
# $4: SSH port (optional, uses SSH_PORT if not provided)
170+
suggest_available_port() {
171+
local preferred=$1
172+
local user=${2:-$SSH_USER}
173+
local host=${3:-$SSH_HOST}
174+
local ssh_port=${4:-$SSH_PORT}
175+
176+
# If preferred port is provided and available, use it
177+
if [ -n "$preferred" ]; then
178+
if check_remote_port_available "$preferred" "$user" "$host" "$ssh_port"; then
179+
echo "$preferred"
180+
return 0
181+
fi
182+
fi
183+
184+
# Try common app ports 3000-3010
185+
for port in 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010; do
186+
if check_remote_port_available "$port" "$user" "$host" "$ssh_port"; then
187+
echo "$port"
188+
return 0
189+
fi
190+
done
191+
192+
# Fall back to random high port (8080-8099 range)
193+
for port in 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099; do
194+
if check_remote_port_available "$port" "$user" "$host" "$ssh_port"; then
195+
echo "$port"
196+
return 0
197+
fi
198+
done
199+
200+
# Last resort: generate random port in ephemeral range
201+
echo $((49152 + RANDOM % 16384))
202+
}
203+
124204
# Parse users.yml file

0 commit comments

Comments
 (0)