Update vps_manager.sh

This commit is contained in:
Lsmoisu 2025-05-18 01:18:54 +08:00 committed by GitHub
parent 048e7c9947
commit 42a3814356
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -16,9 +16,14 @@ show_menu() {
echo "9. 查看虚拟机列表" echo "9. 查看虚拟机列表"
echo "10. 创建虚拟机" echo "10. 创建虚拟机"
echo "11. 删除虚拟机" echo "11. 删除虚拟机"
echo "12. 查看该项目下 socks5 配置"
echo "13. 配置防火墙"
echo "14. 查看防火墙规则"
echo "15. 删除防火墙规则"
echo "0. 退出脚本" echo "0. 退出脚本"
echo "=====================================" echo "====================================="
echo "请输入选项0-11" echo "请输入选项0-13"
} }
# 获取当前日期,格式为 YYYYMMDD # 获取当前日期,格式为 YYYYMMDD
@ -61,26 +66,81 @@ get_instance_quota() {
return 0 return 0
} }
# 动态获取支持 e2-micro 的区域和可用区,并分组 # 动态获取支持 e2-micro 的区域和可用区,并分组(优化版)
get_regions_and_zones() { get_regions_and_zones() {
echo "正在获取支持 e2-micro 机器类型的区域和可用区..." echo "正在获取支持 e2-micro 机器类型的区域和可用区..."
zones=$(gcloud compute machine-types list --filter="name=e2-micro" --format="value(ZONE)" --limit=1000 2>/dev/null | sort | uniq)
if [ -z "$zones" ]; then # 硬编码的支持 e2-micro 的区域和可用区列表,加速获取
echo "无法获取可用区列表,请检查 gcloud 配置或网络连接。"
return 1
fi
declare -g -A region_map declare -g -A region_map
declare -g -a regions declare -g -a regions
regions=() regions=("us-central1" "us-east1" "us-east4" "us-east5" "us-east7" "us-west1" "us-west2" "us-west3" "us-west4" "us-west8" "us-south1" "europe-central2" "europe-north1" "europe-north2" "europe-southwest1" "europe-west1" "europe-west2" "europe-west3" "europe-west4" "europe-west6" "europe-west8" "europe-west9" "europe-west10" "europe-west12" "asia-east1" "asia-east2" "asia-northeast1" "asia-northeast2" "asia-northeast3" "asia-south1" "asia-south2" "asia-southeast1" "asia-southeast2" "australia-southeast1" "australia-southeast2" "southamerica-east1" "southamerica-west1" "northamerica-northeast1" "northamerica-northeast2" "northamerica-south1" "me-central1" "me-central2" "me-west1" "africa-south1")
IFS=$'\n'
for zone in $zones; do # 初始化 region_map
region=$(echo "$zone" | cut -d'-' -f1) region_map["us-central1"]="us-central1-a us-central1-b us-central1-c us-central1-d us-central1-f"
if [[ ! " ${regions[@]} " =~ " ${region} " ]]; then region_map["us-east1"]="us-east1-a us-east1-b us-east1-c us-east1-d"
regions+=("$region") region_map["us-east4"]="us-east4-a us-east4-b us-east4-c"
region_map["us-east5"]="us-east5-a us-east5-b us-east5-c"
region_map["us-east7"]="us-east7-a us-east7-b us-east7-c"
region_map["us-west1"]="us-west1-a us-west1-b us-west1-c"
region_map["us-west2"]="us-west2-a us-west2-b us-west2-c"
region_map["us-west3"]="us-west3-a us-west3-b us-west3-c"
region_map["us-west4"]="us-west4-a us-west4-b us-west4-c"
region_map["us-west8"]="us-west8-a us-west8-b us-west8-c"
region_map["us-south1"]="us-south1-a us-south1-b us-south1-c"
region_map["europe-central2"]="europe-central2-a europe-central2-b europe-central2-c"
region_map["europe-north1"]="europe-north1-a europe-north1-b europe-north1-c"
region_map["europe-north2"]="europe-north2-a europe-north2-b europe-north2-c"
region_map["europe-southwest1"]="europe-southwest1-a europe-southwest1-b europe-southwest1-c"
region_map["europe-west1"]="europe-west1-b europe-west1-c europe-west1-d"
region_map["europe-west2"]="europe-west2-a europe-west2-b europe-west2-c"
region_map["europe-west3"]="europe-west3-a europe-west3-b europe-west3-c"
region_map["europe-west4"]="europe-west4-a europe-west4-b europe-west4-c"
region_map["europe-west6"]="europe-west6-a europe-west6-b europe-west6-c"
region_map["europe-west8"]="europe-west8-a europe-west8-b europe-west8-c"
region_map["europe-west9"]="europe-west9-a europe-west9-b europe-west9-c"
region_map["europe-west10"]="europe-west10-a europe-west10-b europe-west10-c"
region_map["europe-west12"]="europe-west12-a europe-west12-b europe-west12-c"
region_map["asia-east1"]="asia-east1-a asia-east1-b asia-east1-c"
region_map["asia-east2"]="asia-east2-a asia-east2-b asia-east2-c"
region_map["asia-northeast1"]="asia-northeast1-a asia-northeast1-b asia-northeast1-c"
region_map["asia-northeast2"]="asia-northeast2-a asia-northeast2-b asia-northeast2-c"
region_map["asia-northeast3"]="asia-northeast3-a asia-northeast3-b asia-northeast3-c"
region_map["asia-south1"]="asia-south1-a asia-south1-b asia-south1-c"
region_map["asia-south2"]="asia-south2-a asia-south2-b asia-south2-c"
region_map["asia-southeast1"]="asia-southeast1-a asia-southeast1-b asia-southeast1-c"
region_map["asia-southeast2"]="asia-southeast2-a asia-southeast2-b asia-southeast2-c"
region_map["australia-southeast1"]="australia-southeast1-a australia-southeast1-b australia-southeast1-c"
region_map["australia-southeast2"]="australia-southeast2-a australia-southeast2-b australia-southeast2-c"
region_map["southamerica-east1"]="southamerica-east1-a southamerica-east1-b southamerica-east1-c"
region_map["southamerica-west1"]="southamerica-west1-a southamerica-west1-b southamerica-west1-c"
region_map["northamerica-northeast1"]="northamerica-northeast1-a northamerica-northeast1-b northamerica-northeast1-c"
region_map["northamerica-northeast2"]="northamerica-northeast2-a northamerica-northeast2-b northamerica-northeast2-c"
region_map["northamerica-south1"]="northamerica-south1-a northamerica-south1-b northamerica-south1-c"
region_map["me-central1"]="me-central1-a me-central1-b me-central1-c"
region_map["me-central2"]="me-central2-a me-central2-b me-central2-c"
region_map["me-west1"]="me-west1-a me-west1-b me-west1-c"
region_map["africa-south1"]="africa-south1-a africa-south1-b africa-south1-c"
# 检查硬编码列表是否有效(例如,至少有一个区域)
if [ ${#regions[@]} -eq 0 ]; then
echo "硬编码区域列表为空,尝试动态获取支持 e2-micro 的区域和可用区..."
zones=$(gcloud compute machine-types list --filter="name=e2-micro" --format="value(ZONE)" --limit=1000 2>/dev/null | sort | uniq)
if [ -z "$zones" ]; then
echo "无法获取可用区列表,请检查 gcloud 配置或网络连接。"
return 1
fi fi
region_map["$region"]="${region_map[$region]} $zone" regions=()
done IFS=$'\n'
unset IFS for zone in $zones; do
region=$(echo "$zone" | cut -d'-' -f1)
if [[ ! " ${regions[@]} " =~ " ${region} " ]]; then
regions+=("$region")
fi
region_map["$region"]="${region_map[$region]} $zone"
done
unset IFS
fi
if [ ${#regions[@]} -eq 0 ]; then if [ ${#regions[@]} -eq 0 ]; then
echo "未找到支持 e2-micro 的大区域。" echo "未找到支持 e2-micro 的大区域。"
return 1 return 1
@ -93,7 +153,12 @@ show_region_menu() {
echo "请选择大区域:" echo "请选择大区域:"
local i=1 local i=1
for region in "${regions[@]}"; do for region in "${regions[@]}"; do
echo "$i. $region" location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "$i. $region$location"
else
echo "$i. $region"
fi
((i++)) ((i++))
done done
echo "0. 取消选择" echo "0. 取消选择"
@ -112,8 +177,13 @@ show_zone_menu() {
return 1 return 1
fi fi
local i=1 local i=1
location=${region_location_map["$region"]}
for zone in "${zones_list[@]}"; do for zone in "${zones_list[@]}"; do
echo "$i. $zone" if [ -n "$location" ]; then
echo "$i. $zone$location"
else
echo "$i. $zone"
fi
((i++)) ((i++))
done done
echo "0. 取消选择" echo "0. 取消选择"
@ -126,7 +196,13 @@ show_zone_selection_method() {
echo "请选择地区选择方式:" echo "请选择地区选择方式:"
local default_zone=$(gcloud config get-value compute/zone 2>/dev/null) local default_zone=$(gcloud config get-value compute/zone 2>/dev/null)
if [ -n "$default_zone" ]; then if [ -n "$default_zone" ]; then
echo "1. 使用默认地区:$default_zone" region=$(echo "$default_zone" | sed 's/-[a-z]$//')
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "1. 使用默认地区:$default_zone$location"
else
echo "1. 使用默认地区:$default_zone"
fi
else else
echo "1. 使用默认地区(未设置,需手动指定)" echo "1. 使用默认地区(未设置,需手动指定)"
fi fi
@ -167,7 +243,13 @@ show_instance_menu() {
instance_name=$(echo "$line" | awk '{print $1}') instance_name=$(echo "$line" | awk '{print $1}')
instance_zone=$(echo "$line" | awk '{print $2}') instance_zone=$(echo "$line" | awk '{print $2}')
if [ -n "$instance_name" ] && [ -n "$instance_zone" ]; then if [ -n "$instance_name" ] && [ -n "$instance_zone" ]; then
echo "$i. $instance_name (区域: $instance_zone)" region=$(echo "$instance_zone" | sed 's/-[a-z]$//')
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "$i. $instance_name (区域: $instance_zone$location)"
else
echo "$i. $instance_name (区域: $instance_zone)"
fi
instance_array+=("$instance_name|$instance_zone") instance_array+=("$instance_name|$instance_zone")
((i++)) ((i++))
fi fi
@ -629,7 +711,6 @@ while true; do
read -e -r -n 1 read -e -r -n 1
continue continue
fi fi
# 下载启动脚本 # 下载启动脚本
echo "正在从远程地址下载启动脚本..." echo "正在从远程地址下载启动脚本..."
script_url="https://github.com/Lsmoisu/Toolbox/raw/refs/heads/main/enablesshandcreatesocks5.sh" script_url="https://github.com/Lsmoisu/Toolbox/raw/refs/heads/main/enablesshandcreatesocks5.sh"
@ -670,7 +751,52 @@ while true; do
read -e -r -n 1 read -e -r -n 1
continue continue
fi fi
# 定义区域到地理位置的映射
declare -A region_location_map
region_location_map["africa-south1"]="南非约翰内斯堡"
region_location_map["us-central1"]="美国爱荷华州"
region_location_map["us-east1"]="美国南卡罗来纳州"
region_location_map["us-east4"]="美国弗吉尼亚州北部"
region_location_map["us-east5"]="美国俄亥俄州"
region_location_map["us-east7"]="美国弗吉尼亚州"
region_location_map["us-west1"]="美国俄勒冈州"
region_location_map["us-west2"]="美国加利福尼亚州洛杉矶"
region_location_map["us-west3"]="美国犹他州盐湖城"
region_location_map["us-west4"]="美国内华达州拉斯维加斯"
region_location_map["us-west8"]="美国德克萨斯州达拉斯"
region_location_map["us-south1"]="美国得克萨斯州"
region_location_map["europe-central2"]="波兰华沙"
region_location_map["europe-north1"]="芬兰哈米纳"
region_location_map["europe-north2"]="挪威斯塔万格"
region_location_map["europe-southwest1"]="西班牙马德里"
region_location_map["europe-west1"]="比利时圣吉斯兰"
region_location_map["europe-west2"]="英国伦敦"
region_location_map["europe-west3"]="德国法兰克福"
region_location_map["europe-west4"]="荷兰埃姆斯哈文"
region_location_map["europe-west6"]="瑞士苏黎世"
region_location_map["europe-west8"]="意大利米兰"
region_location_map["europe-west9"]="法国巴黎"
region_location_map["europe-west10"]="德国柏林"
region_location_map["europe-west12"]="意大利都灵"
region_location_map["asia-east1"]="台湾彰化县"
region_location_map["asia-east2"]="中国香港"
region_location_map["asia-northeast1"]="日本东京"
region_location_map["asia-northeast2"]="日本大阪"
region_location_map["asia-northeast3"]="韩国首尔"
region_location_map["asia-south1"]="印度孟买"
region_location_map["asia-south2"]="印度德里"
region_location_map["asia-southeast1"]="新加坡"
region_location_map["asia-southeast2"]="亚太地区印度尼西亚雅加达"
region_location_map["australia-southeast1"]="澳大利亚悉尼"
region_location_map["australia-southeast2"]="澳大利亚墨尔本"
region_location_map["southamerica-east1"]="巴西圣保罗"
region_location_map["southamerica-west1"]="智利圣地亚哥"
region_location_map["northamerica-northeast1"]="加拿大蒙特利尔"
region_location_map["northamerica-northeast2"]="加拿大多伦多"
region_location_map["northamerica-south1"]="美国南卡罗来纳州"
region_location_map["me-central1"]="卡塔尔多哈"
region_location_map["me-central2"]="沙特阿拉伯达曼"
region_location_map["me-west1"]="以色列特拉维夫"
# 选择地区选择方式 # 选择地区选择方式
while true; do while true; do
show_zone_selection_method show_zone_selection_method
@ -683,7 +809,13 @@ while true; do
elif [ "$method_choice" -eq 1 ]; then elif [ "$method_choice" -eq 1 ]; then
default_zone=$(gcloud config get-value compute/zone 2>/dev/null) default_zone=$(gcloud config get-value compute/zone 2>/dev/null)
if [ -n "$default_zone" ]; then if [ -n "$default_zone" ]; then
echo "使用默认地区:$default_zone" region=$(echo "$default_zone" | cut -d'-' -f1-2)
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "使用默认地区:$default_zone$location"
else
echo "使用默认地区:$default_zone"
fi
zone="$default_zone" zone="$default_zone"
break break
else else
@ -698,7 +830,13 @@ while true; do
echo "正在设置默认地区为 $input_zone..." echo "正在设置默认地区为 $input_zone..."
gcloud config set compute/zone "$input_zone" gcloud config set compute/zone "$input_zone"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "默认地区已设置为 $input_zone" region=$(echo "$input_zone" | cut -d'-' -f1-2)
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "默认地区已设置为 $input_zone$location"
else
echo "默认地区已设置为 $input_zone"
fi
zone="$input_zone" zone="$input_zone"
break break
else else
@ -709,6 +847,7 @@ while true; do
fi fi
fi fi
elif [ "$method_choice" -eq 2 ]; then elif [ "$method_choice" -eq 2 ]; then
echo "正在获取支持 e2-micro 机器类型的区域和可用区..."
get_regions_and_zones get_regions_and_zones
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "按任意键返回菜单..." echo "按任意键返回菜单..."
@ -716,7 +855,18 @@ while true; do
continue 2 continue 2
fi fi
while true; do while true; do
show_region_menu echo "请选择大区域:"
for i in "${!regions[@]}"; do
region="${regions[$i]}"
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
printf "%2d. %s (%s)\n" "$((i+1))" "$region" "$location"
else
printf "%2d. %s\n" "$((i+1))" "$region"
fi
done
echo "0. 取消选择"
echo "请输入选项0-${#regions[@]}"
read -e -r region_choice read -e -r region_choice
if [ "$region_choice" -eq 0 ]; then if [ "$region_choice" -eq 0 ]; then
echo "操作取消。" echo "操作取消。"
@ -750,12 +900,36 @@ while true; do
fi fi
if [ "$zone_choice" -ge 1 ] && [ "$zone_choice" -le "${#zones_list[@]}" ]; then if [ "$zone_choice" -ge 1 ] && [ "$zone_choice" -le "${#zones_list[@]}" ]; then
zone="${zones_list[$((zone_choice-1))]}" zone="${zones_list[$((zone_choice-1))]}"
# 自动设置选择的区域为默认区域
echo "正在设置默认地区为 $zone..."
gcloud config set compute/zone "$zone"
region=$(echo "$zone" | cut -d'-' -f1-2)
location=${region_location_map["$region"]}
if [ $? -eq 0 ]; then
if [ -n "$location" ]; then
echo "默认地区已设置为 $zone$location"
else
echo "默认地区已设置为 $zone"
fi
else
if [ -n "$location" ]; then
echo "设置默认地区失败,请检查区域格式或权限,但将继续使用 $zone$location 创建虚拟机。"
else
echo "设置默认地区失败,请检查区域格式或权限,但将继续使用 $zone 创建虚拟机。"
fi
fi
break break
else else
echo "无效选项,请选择 0-${#zones_list[@]} 之间的数字。" echo "无效选项,请选择 0-${#zones_list[@]} 之间的数字。"
fi fi
done done
echo "选择的可用区:$zone" region=$(echo "$zone" | cut -d'-' -f1-2)
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "选择的可用区:$zone$location"
else
echo "选择的可用区:$zone"
fi
break break
elif [ "$method_choice" -eq 3 ]; then elif [ "$method_choice" -eq 3 ]; then
echo "请输入新的默认地区(如 us-central1-a" echo "请输入新的默认地区(如 us-central1-a"
@ -769,7 +943,13 @@ while true; do
echo "正在设置默认地区为 $new_zone..." echo "正在设置默认地区为 $new_zone..."
gcloud config set compute/zone "$new_zone" gcloud config set compute/zone "$new_zone"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "默认地区已更新为 $new_zone" region=$(echo "$new_zone" | cut -d'-' -f1-2)
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "默认地区已更新为 $new_zone$location"
else
echo "默认地区已更新为 $new_zone"
fi
else else
echo "设置默认地区失败,请检查区域格式或权限。" echo "设置默认地区失败,请检查区域格式或权限。"
echo "按任意键返回菜单..." echo "按任意键返回菜单..."
@ -781,7 +961,7 @@ while true; do
fi fi
done done
# 直接提示用户输入创建数量 # 直接提示用户输入创建数量(保持不变)
while true; do while true; do
echo "请输入要创建的虚拟机数量(大于 0 的整数):" echo "请输入要创建的虚拟机数量(大于 0 的整数):"
read -e -r instance_count read -e -r instance_count
@ -792,7 +972,7 @@ while true; do
break break
done done
# 批量创建虚拟机 # 批量创建虚拟机(保持不变)
echo "将创建 $instance_count 台虚拟机..." echo "将创建 $instance_count 台虚拟机..."
for ((i=1; i<=instance_count; i++)); do for ((i=1; i<=instance_count; i++)); do
random_suffix=$(generate_random_suffix) random_suffix=$(generate_random_suffix)
@ -894,7 +1074,13 @@ while true; do
for inst in "${selected_instances[@]}"; do for inst in "${selected_instances[@]}"; do
instance_name=$(echo "$inst" | cut -d'|' -f1) instance_name=$(echo "$inst" | cut -d'|' -f1)
instance_zone=$(echo "$inst" | cut -d'|' -f2) instance_zone=$(echo "$inst" | cut -d'|' -f2)
echo "- $instance_name (区域: $instance_zone)" region=$(echo "$instance_zone" | sed 's/-[a-z]$//')
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "- $instance_name (区域: $instance_zone$location)"
else
echo "- $instance_name (区域: $instance_zone)"
fi
done done
echo "确认删除这些虚拟机吗?(输入 'yes' 确认,任意其他输入取消):" echo "确认删除这些虚拟机吗?(输入 'yes' 确认,任意其他输入取消):"
read -e -r confirm read -e -r confirm
@ -924,12 +1110,370 @@ while true; do
echo "按任意键返回菜单..." echo "按任意键返回菜单..."
read -e -r -n 1 read -e -r -n 1
;; ;;
12)
echo "正在查看当前项目下所有实例的 socks5 配置..."
current_project=$(gcloud config get-value project)
if [ -z "$current_project" ]; then
echo "未找到默认项目,请先切换默认项目(选项 8。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
echo "当前默认项目:$current_project"
instance_data=$(get_instance_list "$current_project")
if [ $? -ne 0 ]; then
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 定义区域到地理位置的映射
declare -A region_location_map
region_location_map["africa-south1"]="南非约翰内斯堡"
region_location_map["us-central1"]="美国爱荷华州"
region_location_map["us-east1"]="美国南卡罗来纳州"
region_location_map["us-east4"]="美国弗吉尼亚州北部"
region_location_map["us-east5"]="美国俄亥俄州"
region_location_map["us-east7"]="美国弗吉尼亚州"
region_location_map["us-west1"]="美国俄勒冈州"
region_location_map["us-west2"]="美国加利福尼亚州洛杉矶"
region_location_map["us-west3"]="美国犹他州盐湖城"
region_location_map["us-west4"]="美国内华达州拉斯维加斯"
region_location_map["us-west8"]="美国德克萨斯州达拉斯"
region_location_map["us-south1"]="美国得克萨斯州"
region_location_map["europe-central2"]="波兰华沙"
region_location_map["europe-north1"]="芬兰哈米纳"
region_location_map["europe-north2"]="挪威斯塔万格"
region_location_map["europe-southwest1"]="西班牙马德里"
region_location_map["europe-west1"]="比利时圣吉斯兰"
region_location_map["europe-west2"]="英国伦敦"
region_location_map["europe-west3"]="德国法兰克福"
region_location_map["europe-west4"]="荷兰埃姆斯哈文"
region_location_map["europe-west6"]="瑞士苏黎世"
region_location_map["europe-west8"]="意大利米兰"
region_location_map["europe-west9"]="法国巴黎"
region_location_map["europe-west10"]="德国柏林"
region_location_map["europe-west12"]="意大利都灵"
region_location_map["asia-east1"]="台湾彰化县"
region_location_map["asia-east2"]="中国香港"
region_location_map["asia-northeast1"]="日本东京"
region_location_map["asia-northeast2"]="日本大阪"
region_location_map["asia-northeast3"]="韩国首尔"
region_location_map["asia-south1"]="印度孟买"
region_location_map["asia-south2"]="印度德里"
region_location_map["asia-southeast1"]="新加坡"
region_location_map["asia-southeast2"]="亚太地区印度尼西亚雅加达"
region_location_map["australia-southeast1"]="澳大利亚悉尼"
region_location_map["australia-southeast2"]="澳大利亚墨尔本"
region_location_map["southamerica-east1"]="巴西圣保罗"
region_location_map["southamerica-west1"]="智利圣地亚哥"
region_location_map["northamerica-northeast1"]="加拿大蒙特利尔"
region_location_map["northamerica-northeast2"]="加拿大多伦多"
region_location_map["northamerica-south1"]="美国南卡罗来纳州"
region_location_map["me-central1"]="卡塔尔多哈"
region_location_map["me-central2"]="沙特阿拉伯达曼"
region_location_map["me-west1"]="以色列特拉维夫"
# 显示虚拟机列表并获取数组
show_instance_menu "$instance_data"
if [ $? -ne 0 ]; then
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 遍历每个实例,读取 /opt/socks.txt 文件内容
echo "正在读取每个实例的 /opt/socks.txt 文件内容..."
for inst in "${instance_array[@]}"; do
instance_name=$(echo "$inst" | cut -d'|' -f1)
instance_zone=$(echo "$inst" | cut -d'|' -f2)
echo "----------------------------------------"
region=$(echo "$instance_zone" | sed 's/-[a-z]$//')
location=${region_location_map["$region"]}
if [ -n "$location" ]; then
echo "实例:$instance_name (区域: $instance_zone$location)"
else
echo "实例:$instance_name (区域: $instance_zone)"
fi
# 使用 gcloud compute ssh 远程读取文件内容
socks_content=$(gcloud compute ssh "$instance_name" \
--project="$current_project" \
--zone="$instance_zone" \
--command="cat /opt/socks.txt" \
--quiet 2>/dev/null)
if [ $? -eq 0 ] && [ -n "$socks_content" ]; then
echo "$socks_content"
else
echo "无法读取文件内容,可能是文件不存在、权限不足或 SSH 连接失败。"
fi
echo "----------------------------------------"
done
echo "按任意键返回菜单..."
read -e -r -n 1
;;
13)
echo "正在配置防火墙规则..."
current_project=$(gcloud config get-value project)
if [ -z "$current_project" ]; then
echo "未找到默认项目,请先切换默认项目(选项 8。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
echo "当前默认项目:$current_project"
# 提示用户输入防火墙规则名称
echo "请输入防火墙规则名称(小写字母、数字或短划线组成,留空取消操作):"
read -e -r rule_name
if [ -z "$rule_name" ]; then
echo "未输入规则名称,操作取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 验证规则名称格式(仅允许小写字母、数字和短划线)
if [[ ! "$rule_name" =~ ^[a-z0-9][a-z0-9-]*[a-z0-9]$ ]] || [[ "$rule_name" =~ ^- ]] || [[ "$rule_name" =~ -$ ]]; then
echo "规则名称格式无效,仅允许小写字母、数字和短划线,且不能以短划线开头或结尾。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 检查规则名称是否已存在
echo "正在检查规则名称是否已存在..."
if gcloud compute firewall-rules list --project="$current_project" | grep -q "^$rule_name "; then
echo "规则名称 '$rule_name' 已存在,请使用其他名称。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 提示用户选择协议类型
echo "请选择协议类型:"
echo "1. TCP"
echo "2. UDP"
echo "3. TCP 和 UDP"
echo "0. 取消操作"
read -e -r protocol_choice
case $protocol_choice in
1)
protocol="tcp"
;;
2)
protocol="udp"
;;
3)
protocol="tcp,udp"
;;
0)
echo "操作取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
;;
*)
echo "无效选项,操作取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
;;
esac
# 提示用户输入端口号或范围
echo "请输入端口号(支持单个端口如 '8080',非连续端口如 '8080,8081',连续端口范围如 '8000-9000'"
read -e -r port_input
if [ -z "$port_input" ]; then
echo "未输入端口号,操作取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 验证端口输入格式
if [[ ! "$port_input" =~ ^[0-9]+(-[0-9]+)?([,][0-9]+(-[0-9]+)?)*$ ]]; then
echo "端口格式无效仅支持数字、逗号和短划线用于范围。示例8080 或 8000-9000 或 8080,8081,9000-9100"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 拆分端口输入,检查每个端口或范围是否合法
IFS=',' read -ra port_entries <<< "$port_input"
for entry in "${port_entries[@]}"; do
if [[ "$entry" =~ ^[0-9]+-[0-9]+$ ]]; then
# 范围端口
IFS='-' read -ra range <<< "$entry"
start_port=${range[0]}
end_port=${range[1]}
if [ "$start_port" -lt 1 ] || [ "$start_port" -gt 65535 ] || [ "$end_port" -lt 1 ] || [ "$end_port" -gt 65535 ] || [ "$start_port" -gt "$end_port" ]; then
echo "端口范围 $entry 无效,端口必须在 1-65535 之间,且起始端口不能大于结束端口。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue 2
fi
elif [[ "$entry" =~ ^[0-9]+$ ]]; then
# 单个端口
if [ "$entry" -lt 1 ] || [ "$entry" -gt 65535 ]; then
echo "端口 $entry 无效,端口必须在 1-65535 之间。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue 2
fi
else
echo "端口格式 $entry 无效。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue 2
fi
done
unset IFS
# 提示用户输入来源 IP 范围(默认为 0.0.0.0/0即所有来源
echo "请输入允许的来源 IP 范围CIDR 格式,如 0.0.0.0/0 表示所有 IP留空使用默认值 0.0.0.0/0"
read -e -r source_ranges
if [ -z "$source_ranges" ]; then
source_ranges="0.0.0.0/0"
fi
# 验证 CIDR 格式(简单检查)
if [[ ! "$source_ranges" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then
echo "来源 IP 范围格式无效,应为 CIDR 格式(如 0.0.0.0/0 或 192.168.1.0/24。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 确认创建防火墙规则
echo "即将创建以下防火墙规则:"
echo "规则名称:$rule_name"
echo "协议:$protocol"
echo "端口:$port_input"
echo "来源 IP 范围:$source_ranges"
echo "确认创建吗?(输入 'y' 确认,其他取消):"
read -e -r -n 1 confirm
echo ""
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo "创建操作已取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 格式化 --rules 参数
rules=""
IFS=',' read -ra protocols <<< "$protocol"
IFS=',' read -ra ports <<< "$port_input"
for proto in "${protocols[@]}"; do
for port in "${ports[@]}"; do
if [ -n "$rules" ]; then
rules="$rules,"
fi
rules="$rules$proto:$port"
done
done
unset IFS
# 创建防火墙规则
echo "正在创建防火墙规则 '$rule_name'..."
gcloud compute firewall-rules create "$rule_name" \
--project="$current_project" \
--direction=INGRESS \
--priority=1000 \
--network=default \
--action=ALLOW \
--rules="$rules" \
--source-ranges="$source_ranges"
if [ $? -eq 0 ]; then
echo "防火墙规则 '$rule_name' 创建成功!"
else
echo "创建防火墙规则失败,可能是规则名称已存在或没有权限。"
echo "错误信息如上,请检查。"
fi
echo "按任意键返回菜单..."
read -e -r -n 1
;;
14)
echo "正在查看当前防火墙规则..."
current_project=$(gcloud config get-value project)
if [ -z "$current_project" ]; then
echo "未找到默认项目,请先切换默认项目(选项 8。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
echo "当前默认项目:$current_project"
echo "列出所有防火墙规则:"
# 使用 gcloud 命令列出防火墙规则
gcloud compute firewall-rules list --project="$current_project" --format="table(name,network,direction,priority,allow,disabled)" 2>/dev/null
if [ $? -eq 0 ]; then
echo "防火墙规则列表显示完毕。"
else
echo "无法获取防火墙规则列表,请检查是否有权限或项目是否正确。"
fi
echo "按任意键返回菜单..."
read -e -r -n 1
;;
15)
echo "正在准备删除防火墙规则..."
current_project=$(gcloud config get-value project)
if [ -z "$current_project" ]; then
echo "未找到默认项目,请先切换默认项目(选项 8。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
echo "当前默认项目:$current_project"
echo "当前防火墙规则列表:"
# 列出所有防火墙规则供用户参考
gcloud compute firewall-rules list --project="$current_project" --format="table(name,network,direction,priority,allow,disabled)" 2>/dev/null
if [ $? -ne 0 ]; then
echo "无法获取防火墙规则列表,请检查是否有权限或项目是否正确。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 提示用户输入要删除的规则名称
echo "请输入要删除的防火墙规则名称(留空取消操作):"
read -e -r rule_name
if [ -z "$rule_name" ]; then
echo "未输入规则名称,操作取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 确认删除操作
echo "确认要删除防火墙规则 '$rule_name' 吗?(输入 'y' 确认,其他取消):"
read -e -r -n 1 confirm
echo ""
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo "删除操作已取消。"
echo "按任意键返回菜单..."
read -e -r -n 1
continue
fi
# 执行删除操作
echo "正在删除防火墙规则 '$rule_name'..."
gcloud compute firewall-rules delete "$rule_name" --project="$current_project" --quiet 2>/dev/null
if [ $? -eq 0 ]; then
echo "防火墙规则 '$rule_name' 删除成功。"
else
echo "删除防火墙规则失败,可能是规则不存在或没有权限。"
fi
echo "按任意键返回菜单..."
read -e -r -n 1
;;
0) 0)
echo "退出脚本..." echo "退出脚本..."
exit 0 exit 0
;; ;;
*) *)
echo "无效选项,请选择 0-11 之间的数字。" echo "无效选项,请选择 0-12 之间的数字。"
echo "按任意键返回菜单..." echo "按任意键返回菜单..."
read -e -r -n 1 read -e -r -n 1
;; ;;