clean commit

This commit is contained in:
sushen339
2025-10-17 02:14:17 +08:00
commit ca016e8fca
6 changed files with 2342 additions and 0 deletions
+726
View File
@@ -0,0 +1,726 @@
#!/bin/bash
# mssh - SSH 管理工具
# 配置文件路径
CONFIG_FILE="$HOME/.mssh.conf"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
ORANGE='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# Emoji 定义
SERVER_EMOJI="🌐"
KEY_EMOJI="🔑"
PASSWORD_EMOJI="🔒"
CONNECT_EMOJI="🔌"
SUCCESS_EMOJI="✅"
ERROR_EMOJI="❌"
WARNING_EMOJI="⚠️"
INFO_EMOJI="𝒊"
FORWARD_EMOJI="📡"
# 信号处理
graceful_exit() {
echo -e "\n${INFO_EMOJI} ${CYAN} 正在退出 mssh...${NC}"
# 检查是否有活跃的端口转发
local active_forwards
active_forwards=$(get_section "active_forwards")
if [ -n "$active_forwards" ]; then
echo -e "${WARNING_EMOJI} ${YELLOW}检测到活跃的端口转发进程${NC}"
echo -e "${INFO_EMOJI} ${CYAN}这些进程将继续在后台运行${NC}"
echo -e "${CYAN}您可以随时重新启动 mssh 来管理它们${NC}"
echo
# 显示活跃的转发
local i=1
while IFS='|' read -r rule_name local_port pid user_host port server_alias remote_host remote_port; do
[ -z "$rule_name" ] && continue
printf " ${GREEN}%2d.${NC} ${FORWARD_EMOJI} ${YELLOW}%s${NC} (PID:%s)\n" "$i" "$rule_name" "$pid"
((i++))
done <<< "$active_forwards"
fi
echo -e "\n🔚 脚本已退出"
exit 0
}
# 设置信号处理
trap graceful_exit SIGINT SIGTERM SIGQUIT
# 密码加密函数
encrypt_password() {
local password="$1"
[ -z "$password" ] && return
# 简单的字符位移 + base64
local encrypted
encrypted=$(echo "$password" | tr 'A-Za-z0-9' 'N-ZA-Mn-za-m5-90-4' | base64 -w 0)
echo "ENC:$encrypted"
}
# 密码解密函数
decrypt_password() {
local encrypted="$1"
[ -z "$encrypted" ] && return
# 解密格式:ENC:base64data
if [[ "$encrypted" =~ ^ENC: ]]; then
local encrypted_data="${encrypted#ENC:}"
echo "$encrypted_data" | base64 -d | tr 'N-ZA-Mn-za-m5-90-4' 'A-Za-z0-9'
fi
}
# 安全读取函数
safe_read() {
local prompt="$1"
local var_name="$2"
local response
if ! read -r -p "$prompt" response; then
graceful_exit
fi
if [ -n "$var_name" ]; then
eval "$var_name=\"$response\""
fi
}
# 检查 sshpass
check_sshpass() {
if ! command -v sshpass >/dev/null 2>&1; then
echo -e "${ERROR_EMOJI} ${RED}未找到 sshpass。某些功能可能不可用。${NC}"
echo -e "${INFO_EMOJI} ${YELLOW}可以运行以下命令安装:${NC}"
echo -e " ${CYAN}Ubuntu/Debian: sudo apt install sshpass${NC}"
echo -e " ${CYAN}CentOS/RHEL: sudo yum install sshpass${NC}"
fi
}
# 初始化配置文件
init_config() {
if [ ! -f "$CONFIG_FILE" ]; then
cat > "$CONFIG_FILE" << 'EOF'
# mssh 配置文件
# 格式说明:
# [servers] 部分:alias|user@host|port|keypath|encrypted_password
# [port_forwards] 部分:server_alias|rule_name|local_port|remote_host|remote_port|user@host|port|keypath|encrypted_password
# [active_forwards] 部分:rule_name|local_port|pid|user@host|port|server_alias|remote_host|remote_port
[servers]
[port_forwards]
[active_forwards]
EOF
echo -e "${SUCCESS_EMOJI} ${GREEN}配置文件已创建: $CONFIG_FILE${NC}"
fi
}
# 获取配置文件中的特定部分
get_section() {
local section="$1"
local config_file="${2:-$CONFIG_FILE}"
awk -v section="[$section]" '
$0 == section { in_section = 1; next }
/^\[.*\]$/ { in_section = 0; next }
in_section && NF > 0 && !/^#/ { print }
' "$config_file"
}
# 格式化端口转发显示
format_forward_display() {
local num="$1"
local rule_name="$2"
local local_port="$3"
local server_alias="$4"
local remote_host="$5"
local remote_port="$6"
local pid="$7"
local pid_text=""
[ -n "$pid" ] && pid_text=" PID:$pid"
if [ "$remote_host" = "127.0.0.1" ]; then
printf " ${GREEN}%2d.${NC} ${FORWARD_EMOJI} ${YELLOW}%s${NC} (本地:%s -> %s:%s)%s\n" \
"$num" "$rule_name" "$local_port" "$server_alias" "$remote_port" "$pid_text"
else
printf " ${GREEN}%2d.${NC} ${FORWARD_EMOJI} ${YELLOW}%s${NC} (本地:%s -> %s -> %s:%s)%s\n" \
"$num" "$rule_name" "$local_port" "$server_alias" "$remote_host" "$remote_port" "$pid_text"
fi
}
# 显示服务器列表
show_servers() {
echo -e "${CYAN}已保存的服务器:${NC}"
echo -e "${CYAN}---------------${NC}"
local servers
servers=$(get_section "servers")
if [ -z "$servers" ]; then
echo -e " ${YELLOW}暂无服务器${NC}"
return 0
fi
local i=1
while IFS='|' read -r alias_name user_host port key_path password; do
[ -z "$alias_name" ] && continue
# 显示密码和密钥状态
local has_password=""
local has_key=""
[ -n "$password" ] && has_password="${PASSWORD_EMOJI}"
[ -n "$key_path" ] && [ -f "$key_path" ] && has_key="${KEY_EMOJI}"
printf " ${GREEN}%2d.${NC} ${SERVER_EMOJI} ${YELLOW}%s${NC} (%s:%s) %s%s\n" \
"$i" "$alias_name" "$user_host" "$port" "$has_password" "$has_key"
((i++))
done <<< "$servers"
return $((i-1))
}
# 显示活跃的端口转发
show_active_forwards() {
local active_forwards
active_forwards=$(get_section "active_forwards")
if [ -n "$active_forwards" ]; then
echo
echo -e "${CYAN}已启用的端口转发:${NC}"
echo -e "${CYAN}------------------${NC}"
local i=1
while IFS='|' read -r rule_name local_port pid user_host port server_alias remote_host remote_port; do
[ -z "$rule_name" ] && continue
format_forward_display "$i" "$rule_name" "$local_port" "$server_alias" "$remote_host" "$remote_port" "$pid"
((i++))
done <<< "$active_forwards"
return 0
else
return 1
fi
}
# 检查并清理无效的端口转发进程
check_and_cleanup_forwards() {
local active_forwards
active_forwards=$(get_section "active_forwards")
if [ -z "$active_forwards" ]; then
return 0
fi
local temp_file
temp_file=$(mktemp)
local cleanup_needed=false
local cleaned_count=0
# 复制配置文件到临时文件
cp "$CONFIG_FILE" "$temp_file"
while IFS='|' read -r rule_name local_port pid user_host port server_alias remote_host remote_port; do
[ -z "$rule_name" ] && continue
# 检查进程是否存在
if ! kill -0 "$pid" 2>/dev/null; then
# 进程不存在,从配置中移除
local rule_line="${rule_name}|${local_port}|${pid}|${user_host}|${port}|${server_alias}|${remote_host}|${remote_port}"
awk -v target_line="$rule_line" '
$0 == target_line && in_active { next }
/^\[active_forwards\]$/ { in_active=1 }
/^\[.*\]$/ && !/^\[active_forwards\]$/ { in_active=0 }
{ print }
' "$temp_file" > "${temp_file}.new" && mv "${temp_file}.new" "$temp_file"
cleanup_needed=true
((cleaned_count++))
fi
done <<< "$active_forwards"
# 如果有清理,更新配置文件并显示信息
if [ "$cleanup_needed" = true ]; then
mv "$temp_file" "$CONFIG_FILE"
if [ "$cleaned_count" -gt 0 ]; then
echo -e "${INFO_EMOJI} ${YELLOW}已清理 $cleaned_count 个失效的端口转发进程${NC}"
sleep 1
fi
else
rm -f "$temp_file"
fi
}
# 主菜单
main_menu() {
# 在显示菜单前检查并清理无效的端口转发进程
check_and_cleanup_forwards
clear
echo -e "${PURPLE}==========================================${NC}"
echo -e "${PURPLE}:: mssh - SSH 管理工具 ::${NC}"
echo -e "${PURPLE}==========================================${NC}"
echo
show_servers
show_active_forwards
local has_active_forwards=$?
echo
echo -e "${BLUE}选项分区:${NC}"
echo -e "${BLUE}---------${NC}"
echo -e " ${GREEN}[a] 增加服务器${NC}"
echo -e " ${RED}[d] 删除服务器${NC}"
echo -e " ${BLUE}[p] 端口转发${NC}"
echo -e " ${CYAN}[q] 退出${NC}"
# 显示端口转发持久化提示
if [ $has_active_forwards -eq 0 ]; then
echo
echo -e "${INFO_EMOJI} ${YELLOW}提示:端口转发将在退出程序后继续运行${NC}"
fi
echo
echo -ne "${GREEN}请选择操作: ${NC}"
}
# 添加服务器
add_server() {
while true; do
clear
echo -e "${PURPLE}============ 添加服务器 ============${NC}"
echo
echo -e "${INFO_EMOJI} ${CYAN}添加新服务器 (0或回车返回)${NC}"
echo
safe_read "$(echo -e "${CYAN}输入别名: ${NC}")" alias_name; [ "$alias_name" = "0" ] || [ -z "$alias_name" ] && return
safe_read "$(echo -e "${CYAN}输入用户名@主机: ${NC}")" user_host; [ "$user_host" = "0" ] || [ -z "$user_host" ] && return
safe_read "$(echo -e "${CYAN}输入端口 (默认22): ${NC}")" port; [ "$port" = "0" ] && return; port=${port:-22}
echo -ne "${CYAN}输入密码 (可选): ${NC}"
read -r -s password
echo
safe_read "$(echo -e "${CYAN}输入私钥路径 (可选): ${NC}")" key_path; [ "$key_path" = "0" ] && return
if [ -n "$key_path" ] && [ ! -f "$key_path" ]; then
echo -e "${ERROR_EMOJI} ${RED}密钥文件不存在${NC}"
safe_read "$(echo -e "${YELLOW}是否继续? (y/N): ${NC}")" continue_without_key
if [[ ! "${continue_without_key:-n}" =~ [yY] ]]; then
continue
fi
key_path=""
fi
# 加密密码
[ -n "$password" ] && password=$(encrypt_password "$password")
# 添加到配置文件
local temp_file
temp_file=$(mktemp)
awk -v new_server="${alias_name}|${user_host}|${port}|${key_path}|${password}" '
/^\[servers\]$/ { print; in_servers=1; next }
/^\[.*\]$/ { in_servers=0 }
in_servers && /^$/ { print new_server; added=1 }
{ print }
END { if (!added && in_servers) print new_server }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
echo -e "${SUCCESS_EMOJI} ${GREEN}服务器已添加: $alias_name${NC}"
echo
safe_read "$(echo -e "${YELLOW}是否继续添加? (y/N): ${NC}")" continue_add
if [[ ! "${continue_add:-n}" =~ [yY] ]]; then
break
fi
done
}
# 删除服务器
delete_server() {
while true; do
clear
echo -e "${PURPLE}============ 删除服务器 ============${NC}"
echo
echo -e "${WARNING_EMOJI} ${YELLOW}删除服务器${NC}"
echo
show_servers
echo
safe_read "$(echo -e "${CYAN}选择要删除的服务器编号 (0或回车返回): ${NC}")" choice
[ "$choice" = "0" ] || [ -z "$choice" ] && return
local servers
servers=$(get_section "servers")
local server_line
server_line=$(echo "$servers" | sed -n "${choice}p")
if [ -n "$server_line" ]; then
local alias_name
alias_name=$(echo "$server_line" | cut -d'|' -f1)
echo -e "${WARNING_EMOJI} ${YELLOW}确认删除服务器: $alias_name${NC}"
local temp_file
temp_file=$(mktemp)
awk -v target_line="$server_line" '
$0 == target_line && in_servers { next }
/^\[servers\]$/ { in_servers=1 }
/^\[.*\]$/ && !/^\[servers\]$/ { in_servers=0 }
{ print }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
echo -e "${SUCCESS_EMOJI} ${GREEN}服务器已删除: $alias_name${NC}"
else
echo -e "${ERROR_EMOJI} ${RED}无效的服务器编号!${NC}"
fi
echo
safe_read "$(echo -e "${YELLOW}是否继续删除? (y/N): ${NC}")" continue_del
if [[ ! "${continue_del:-n}" =~ [yY] ]]; then
break
fi
done
}
# 添加端口转发规则
add_port_forward_rule() {
echo -e "${INFO_EMOJI} ${CYAN}添加新端口转发规则 (0或回车返回):${NC}"
safe_read "$(echo -e "${CYAN}输入规则名称: ${NC}")" rule_name
if [ "$rule_name" = "0" ] || [ -z "$rule_name" ]; then
return 1
fi
safe_read "$(echo -e "${CYAN}输入本地端口: ${NC}")" local_port
if [ "$local_port" = "0" ] || [ -z "$local_port" ]; then
return 1
fi
safe_read "$(echo -e "${CYAN}输入远程主机 (默认127.0.0.1): ${NC}")" remote_host
if [ "$remote_host" = "0" ]; then
return 1
fi
remote_host=${remote_host:-127.0.0.1}
safe_read "$(echo -e "${CYAN}输入远程端口 (默认${local_port}): ${NC}")" remote_port
if [ "$remote_port" = "0" ]; then
return 1
fi
remote_port=${remote_port:-$local_port}
echo -e "\n${CYAN}请选择要使用的服务器:${NC}"
show_servers
echo
safe_read "$(echo -e "${CYAN}选择服务器编号: ${NC}")" server_choice
if [ "$server_choice" = "0" ] || [ -z "$server_choice" ]; then
return 1
fi
local servers
servers=$(get_section "servers")
local selected_server
selected_server=$(echo "$servers" | sed -n "${server_choice}p")
if [ -n "$selected_server" ]; then
IFS='|' read -r server_alias user_host port key_path password <<< "$selected_server"
local temp_file
temp_file=$(mktemp)
awk -v new_rule="${server_alias}|${rule_name}|${local_port}|${remote_host}|${remote_port}|${user_host}|${port}|${key_path}|${password}" '
/^\[port_forwards\]$/ { print; in_forwards=1; next }
/^\[.*\]$/ { in_forwards=0 }
in_forwards && /^$/ { print new_rule; added=1 }
{ print }
END { if (!added && in_forwards) print new_rule }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
echo -e "${SUCCESS_EMOJI} ${GREEN}端口转发规则已添加: $rule_name${NC}"
return 0
else
echo -e "${ERROR_EMOJI} ${RED}无效的服务器编号!${NC}"
return 1
fi
}
# 删除端口转发规则
delete_port_forward() {
local rule_number="$1"
local forwards
forwards=$(get_section "port_forwards")
local rule_line
rule_line=$(echo "$forwards" | sed -n "${rule_number}p")
if [ -n "$rule_line" ]; then
local rule_name
rule_name=$(echo "$rule_line" | cut -d'|' -f2)
local temp_file
temp_file=$(mktemp)
awk -v target_line="$rule_line" '
$0 == target_line && in_forwards { next }
/^\[port_forwards\]$/ { in_forwards=1 }
/^\[.*\]$/ && !/^\[port_forwards\]$/ { in_forwards=0 }
{ print }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
echo -e "${SUCCESS_EMOJI} ${GREEN}规则已删除: $rule_name${NC}"
else
echo -e "${ERROR_EMOJI} ${RED}无效的规则编号!${NC}"
fi
}
# 停止后台端口转发
stop_background_forward() {
local rule_number="$1"
local active_forwards
active_forwards=$(get_section "active_forwards")
local active_line
active_line=$(echo "$active_forwards" | sed -n "${rule_number}p")
if [ -n "$active_line" ]; then
IFS='|' read -r rule_name local_port pid user_host port server_alias remote_host remote_port <<< "$active_line"
if kill "$pid" 2>/dev/null; then
echo -e "${SUCCESS_EMOJI} ${GREEN}端口转发已停止: $rule_name (PID: $pid)${NC}"
else
echo -e "${WARNING_EMOJI} ${YELLOW}进程可能已经停止: $rule_name (PID: $pid)${NC}"
fi
# 从活跃转发列表中移除
local temp_file
temp_file=$(mktemp)
awk -v target_line="$active_line" '
$0 == target_line && in_active { next }
/^\[active_forwards\]$/ { in_active=1 }
/^\[.*\]$/ && !/^\[active_forwards\]$/ { in_active=0 }
{ print }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
else
echo -e "${ERROR_EMOJI} ${RED}无效的活跃转发编号!${NC}"
fi
}
# 启动后台端口转发
start_background_forward() {
local rule_number="$1"
local forwards
forwards=$(get_section "port_forwards")
local rule_line
rule_line=$(echo "$forwards" | sed -n "${rule_number}p")
if [ -n "$rule_line" ]; then
IFS='|' read -r server_alias rule_name local_port remote_host remote_port user_host port key_path password <<< "$rule_line"
# 解密密码
[ -n "$password" ] && password=$(decrypt_password "$password")
# 构建 SSH 命令
local ssh_args=("-p" "$port" "-L" "${local_port}:${remote_host}:${remote_port}" "-N" "$user_host")
[ -n "$key_path" ] && ssh_args+=("-i" "$key_path")
# 启动后台进程 (使用密码或密钥认证)
local ssh_pid
if [ -n "$password" ] && command -v sshpass >/dev/null 2>&1; then
echo -e "${INFO_EMOJI} ${YELLOW}使用保存的密码启动端口转发...${NC}"
nohup sshpass -p "$password" ssh "${ssh_args[@]}" >/dev/null 2>&1 &
ssh_pid=$!
disown $ssh_pid 2>/dev/null
# 等待SSH连接建立
sleep 1
# 检查进程是否仍在运行
if ! kill -0 "$ssh_pid" 2>/dev/null; then
echo -e "${ERROR_EMOJI} ${RED}端口转发启动失败,请检查网络连接和认证信息${NC}"
return 1
fi
else
echo -e "${INFO_EMOJI} ${YELLOW}启动端口转发 (需要手动输入密码)...${NC}"
nohup ssh "${ssh_args[@]}" </dev/tty >/dev/null 2>&1 &
ssh_pid=$!
disown $ssh_pid 2>/dev/null
# 给用户一些时间输入密码
echo -e "${INFO_EMOJI} ${CYAN}请在上方输入SSH密码...${NC}"
sleep 3
# 检查进程是否仍在运行
if ! kill -0 "$ssh_pid" 2>/dev/null; then
echo -e "${ERROR_EMOJI} ${RED}端口转发启动失败,请检查网络连接和认证信息${NC}"
return 1
fi
fi
local temp_file
temp_file=$(mktemp)
awk -v new_active="${rule_name}|${local_port}|${ssh_pid}|${user_host}|${port}|${server_alias}|${remote_host}|${remote_port}" '
/^\[active_forwards\]$/ { print; in_active=1; next }
/^\[.*\]$/ { in_active=0 }
in_active && /^$/ { print new_active; added=1 }
{ print }
END { if (!added && in_active) print new_active }
' "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
echo -e "${SUCCESS_EMOJI} ${GREEN}端口转发已启动: $rule_name (PID: $ssh_pid)${NC}"
else
echo -e "${ERROR_EMOJI} ${RED}无效的规则编号!${NC}"
fi
}
# 端口转发管理
list_port_forwards() {
while true; do
clear
echo -e "${PURPLE}=========== 端口转发管理 ===========${NC}"
echo
local forwards
forwards=$(get_section "port_forwards")
if [ -z "$forwards" ]; then
echo -e "${CYAN}已配置的端口转发规则:${NC}"
echo -e "${CYAN}------------------------${NC}"
echo -e " ${YELLOW}暂无端口转发规则${NC}"
else
echo -e "${CYAN}已配置的端口转发规则:${NC}"
echo -e "${CYAN}------------------------${NC}"
local i=1
while IFS='|' read -r server_alias rule_name local_port remote_host remote_port _ _ _ _ || [ -n "$rule_name" ]; do
[ -z "$rule_name" ] && continue
format_forward_display "$i" "$rule_name" "$local_port" "$server_alias" "$remote_host" "$remote_port"
((i++))
done <<< "$forwards"
fi
show_active_forwards
echo
echo -e "${BLUE}操作选项:${NC}"
echo -e "${BLUE}---------${NC}"
echo -e " ${GREEN}[1] 添加端口转发${NC}"
echo -e " ${YELLOW}[2] 启动端口转发${NC}"
echo -e " ${ORANGE}[3] 停止端口转发${NC}"
echo -e " ${RED}[4] 删除转发规则${NC}"
echo
safe_read "$(echo -e "${CYAN}请选择操作 (0或回车返回): ${NC}")" choice
case $choice in
0|"") return ;;
1)
echo
if add_port_forward_rule; then
safe_read "按回车键继续..." pause_key
fi
;;
2)
if [ -z "$forwards" ]; then
echo -e "${ERROR_EMOJI} ${RED}暂无端口转发规则可启动!${NC}"
safe_read "按回车键继续..." pause_key
else
safe_read "$(echo -e "${CYAN}输入要启动的规则编号: ${NC}")" start_choice
if [ -n "$start_choice" ]; then
start_background_forward "$start_choice"
fi
safe_read "按回车键继续..." pause_key
fi
;;
3)
local active_forwards
active_forwards=$(get_section "active_forwards")
if [ -z "$active_forwards" ]; then
echo -e "${ERROR_EMOJI} ${RED}暂无活跃的端口转发可停止!${NC}"
safe_read "按回车键继续..." pause_key
else
echo
echo -e "${CYAN}当前活跃的端口转发:${NC}"
local i=1
while IFS='|' read -r rule_name local_port pid user_host port server_alias remote_host remote_port; do
[ -z "$rule_name" ] && continue
format_forward_display "$i" "$rule_name" "$local_port" "$server_alias" "$remote_host" "$remote_port" "$pid"
((i++))
done <<< "$active_forwards"
echo
safe_read "$(echo -e "${CYAN}输入要停止的端口转发编号: ${NC}")" stop_choice
if [ -n "$stop_choice" ]; then
stop_background_forward "$stop_choice"
fi
safe_read "按回车键继续..." pause_key
fi
;;
4)
if [ -z "$forwards" ]; then
echo -e "${ERROR_EMOJI} ${RED}暂无端口转发规则可删除!${NC}"
safe_read "按回车键继续..." pause_key
else
safe_read "$(echo -e "${CYAN}输入要删除的规则编号: ${NC}")" del_choice
if [ -n "$del_choice" ]; then
delete_port_forward "$del_choice"
fi
safe_read "按回车键继续..." pause_key
fi
;;
*) echo -e "${ERROR_EMOJI} ${RED}无效选项!${NC}"; sleep 1 ;;
esac
done
}
# 连接服务器
connect_server() {
local choice=$1
local servers
servers=$(get_section "servers")
local selected_server
selected_server=$(echo "$servers" | sed -n "${choice}p")
if [ -n "$selected_server" ]; then
IFS='|' read -r alias_name user_host port key_path password <<< "$selected_server"
# 解密密码
[ -n "$password" ] && password=$(decrypt_password "$password")
echo -e "${CONNECT_EMOJI} ${GREEN}连接到: $alias_name ($user_host:$port)${NC}"
local ssh_args=("-p" "$port" "$user_host")
[ -n "$key_path" ] && ssh_args+=("-i" "$key_path")
if [ -n "$password" ] && command -v sshpass >/dev/null 2>&1; then
echo -e "${WARNING_EMOJI} ${YELLOW}使用保存的密码连接...${NC}"
sshpass -p "$password" ssh "${ssh_args[@]}"
else
ssh "${ssh_args[@]}"
fi
else
echo -e "${ERROR_EMOJI} ${RED}无效的服务器编号!${NC}"
sleep 1
fi
}
# 主程序
check_sshpass
init_config
while true; do
main_menu
safe_read "" choice
case $choice in
[0-9]*)
if [[ "$choice" =~ ^[0-9]+$ ]]; then
connect_server "$choice"
else
echo -e "${ERROR_EMOJI} ${RED}无效的服务器编号!${NC}"
sleep 1
fi
;;
a|A) add_server ;;
d|D) delete_server ;;
p|P) list_port_forwards ;;
q|Q) graceful_exit ;;
*) echo -e "${ERROR_EMOJI} ${RED}无效选项!${NC}"; sleep 1 ;;
esac
done