Files
s-hy2/install.sh
T
sindricn faf3fcf70a 更新
2025-09-24 16:17:07 +08:00

505 lines
14 KiB
Bash

#!/bin/bash
# Hysteria2 安装脚本 (改进版本)
# 作为 s-hy2 管理脚本的一部分
# 适度的错误处理
set -uo pipefail
# 加载公共库
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "$SCRIPT_DIR/scripts/common.sh" ]]; then
source "$SCRIPT_DIR/scripts/common.sh"
elif [[ -f "$(dirname "$0")/scripts/common.sh" ]]; then
source "$(dirname "$0")/scripts/common.sh"
else
echo "错误: 无法找到公共库 common.sh" >&2
exit 1
fi
# 加载安全模块
if [[ -f "$SCRIPT_DIR/scripts/input-validation.sh" ]]; then
source "$SCRIPT_DIR/scripts/input-validation.sh"
fi
if [[ -f "$SCRIPT_DIR/scripts/secure-download.sh" ]]; then
source "$SCRIPT_DIR/scripts/secure-download.sh"
fi
# 获取系统信息
get_system_info() {
if [[ -f /etc/os-release ]]; then
# shellcheck source=/dev/null
source /etc/os-release
echo "${ID:-unknown} ${VERSION_ID:-unknown}"
else
echo "unknown unknown"
fi
}
# 检查系统兼容性
check_system_compatibility() {
local system_info
system_info=$(get_system_info)
read -r OS_ID VERSION_ID <<< "$system_info"
log_info "检测系统: $OS_ID $VERSION_ID"
case $OS_ID in
ubuntu)
if [[ $(echo "$VERSION_ID >= 18.04" | bc -l 2>/dev/null || echo 0) -eq 1 ]]; then
return 0
fi
;;
debian)
if [[ $(echo "$VERSION_ID >= 9" | bc -l 2>/dev/null || echo 0) -eq 1 ]]; then
return 0
fi
;;
centos|rhel)
if [[ $(echo "$VERSION_ID >= 7" | bc -l 2>/dev/null || echo 0) -eq 1 ]]; then
return 0
fi
;;
fedora)
if [[ $(echo "$VERSION_ID >= 30" | bc -l 2>/dev/null || echo 0) -eq 1 ]]; then
return 0
fi
;;
*)
log_warn "未知系统,将尝试通用安装"
return 0
;;
esac
log_warn "系统版本可能不完全兼容,但将尝试安装"
return 0
}
# 检查网络连接
check_network_connection() {
log_info "检查网络连接..."
local test_urls=(
"https://github.com"
"https://get.hy2.sh"
"https://www.google.com"
"https://raw.githubusercontent.com"
)
local connected=false
# 直接使用 HTTP 连接测试,更可靠
for url in "${test_urls[@]}"; do
if curl -s --connect-timeout 3 --max-time 8 --head "$url" >/dev/null 2>&1; then
connected=true
break
fi
done
if $connected; then
log_success "网络连接正常"
return 0
else
log_error "网络连接检查失败"
echo "请检查:"
echo "1. 网络连接是否正常"
echo "2. DNS 解析是否正常"
echo "3. 防火墙是否阻止了连接"
echo ""
echo "是否继续安装? (可能会失败) [y/N]"
read -r continue_install
if [[ $continue_install =~ ^[Yy]$ ]]; then
return 0
else
return 1
fi
fi
}
# 检查必要的命令
check_required_commands() {
local missing_commands=()
local required_commands=("curl" "systemctl")
for cmd in "${required_commands[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
missing_commands+=("$cmd")
fi
done
if [[ ${#missing_commands[@]} -gt 0 ]]; then
log_error "缺少必要的命令:"
printf ' • %s\n' "${missing_commands[@]}"
echo ""
echo "请先安装这些命令,然后重新运行脚本"
return 1
fi
return 0
}
# 检查端口占用
check_port_usage() {
local port=443
if ss -tlnp | grep -q ":$port "; then
log_warn "端口 $port 已被占用"
echo ""
echo "占用端口 $port 的进程:"
ss -tlnp | grep ":$port " || netstat -tlnp | grep ":$port " 2>/dev/null
echo ""
echo "请处理端口占用后重新安装,或在配置时使用其他端口"
echo ""
echo -n "是否继续安装? [y/N]: "
read -r continue_install
if [[ ! $continue_install =~ ^[Yy]$ ]]; then
return 1
fi
else
log_success "端口 $port 可用"
fi
return 0
}
# 备份现有配置
backup_existing_config() {
if [[ -f "/etc/hysteria/config.yaml" ]]; then
local backup_file="/etc/hysteria/config.yaml.backup.$(date +%Y%m%d_%H%M%S)"
log_info "备份现有配置到: $backup_file"
cp "/etc/hysteria/config.yaml" "$backup_file"
return 0
fi
return 1
}
# 安装 Hysteria2 (安全版本)
install_hysteria2_binary() {
log_info "开始安装 Hysteria2..."
# 加载安全下载模块
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "$script_dir/scripts/secure-download.sh" ]]; then
source "$script_dir/scripts/secure-download.sh"
else
log_warn "安全下载模块未找到,使用基础安全检查"
fi
# 设置安装脚本的环境变量
export HYSTERIA_INSTALL_METHOD="script"
# 安全下载并执行官方安装脚本
local install_script_url="https://get.hy2.sh/"
local temp_script
temp_script=$(mktemp)
chmod 600 "$temp_script" # 设置安全权限
# 设置清理陷阱
trap 'rm -f "$temp_script"' EXIT
log_info "安全下载官方安装脚本..."
# 使用安全下载(如果可用)
if command -v download_script_secure >/dev/null 2>&1; then
if ! download_script_secure "$install_script_url" "$temp_script"; then
log_error "安全下载安装脚本失败"
return 1
fi
else
# 基础安全下载
if ! curl --silent --show-error --fail --location \
--max-time 30 --max-filesize 10485760 \
--proto "=https" --tlsv1.2 \
"$install_script_url" -o "$temp_script"; then
log_error "下载安装脚本失败"
return 1
fi
# 验证脚本内容
if [[ ! -s "$temp_script" ]]; then
log_error "安装脚本为空"
return 1
fi
# 基本语法检查
if ! bash -n "$temp_script"; then
log_error "安装脚本语法错误"
return 1
fi
# 检查危险命令
if grep -qE "rm -rf /|dd if=|mkfs|fdisk" "$temp_script"; then
log_error "安装脚本包含危险命令"
return 1
fi
fi
# 执行安装脚本
log_info "执行安装脚本..."
if timeout 300 bash "$temp_script" --version latest; then
log_success "Hysteria2 安装成功"
return 0
else
log_error "Hysteria2 安装失败"
return 1
fi
}
# 配置系统服务
configure_system_service() {
log_info "配置系统服务..."
# 检查服务文件是否存在
local service_file="/lib/systemd/system/hysteria-server.service"
if [[ ! -f "$service_file" ]] && [[ ! -f "/usr/lib/systemd/system/hysteria-server.service" ]]; then
log_warn "系统服务文件未找到,可能需要手动配置"
return 1
fi
# 重新加载 systemd
systemctl daemon-reload
# 启用服务(但不启动,等配置完成后再启动)
if systemctl enable hysteria-server.service; then
log_success "系统服务配置成功"
return 0
else
log_error "系统服务配置失败"
return 1
fi
}
# 创建配置目录
create_config_directory() {
log_info "创建配置目录..."
if mkdir -p /etc/hysteria; then
# 设置适当的权限
chmod 755 /etc/hysteria
# 如果 hysteria 用户存在,设置所有权
if id hysteria &>/dev/null; then
chown hysteria:hysteria /etc/hysteria
fi
log_success "配置目录创建成功"
return 0
else
log_error "配置目录创建失败"
return 1
fi
}
# 检查安装结果
verify_installation() {
log_info "验证安装结果..."
# 检查二进制文件
if ! command -v hysteria &> /dev/null; then
log_error "Hysteria2 二进制文件未找到"
return 1
fi
# 检查版本
local version
version=$(hysteria version 2>/dev/null | head -1)
if [[ -n "$version" ]]; then
log_success "Hysteria2 安装成功: $version"
else
log_warn "无法获取版本信息,但二进制文件存在"
fi
# 检查系统服务
if systemctl list-unit-files | grep -q hysteria-server; then
log_success "系统服务注册成功"
else
log_warn "系统服务未正确注册"
fi
# 检查用户账户
if id hysteria &>/dev/null; then
log_success "hysteria 用户账户存在"
else
log_warn "hysteria 用户账户不存在"
fi
return 0
}
# 显示安装后信息
show_post_install_info() {
echo ""
echo -e "${CYAN}=== Hysteria2 安装完成 ===${NC}"
echo ""
echo -e "${YELLOW}下一步操作:${NC}"
echo "1. 配置 Hysteria2 服务"
echo " • 选择 '2. 一键快速配置' (推荐新用户)"
echo " • 或选择 '3. 手动配置' (高级用户)"
echo ""
echo "2. 启动服务"
echo " • 配置完成后选择 '4. 管理服务'"
echo ""
echo "3. 查看节点信息"
echo " • 配置完成后选择 '9. 节点信息'"
echo ""
echo -e "${YELLOW}重要提示:${NC}"
echo "• 安装仅完成程序部分,还需要配置才能使用"
echo "• 配置文件将保存在 /etc/hysteria/config.yaml"
echo "• 服务日志可通过 '5. 查看日志' 查看"
echo ""
echo -e "${GREEN}安装位置信息:${NC}"
echo "• 二进制文件: $(which hysteria 2>/dev/null || echo "未找到")"
echo "• 配置目录: /etc/hysteria/"
echo "• 系统服务: hysteria-server.service"
if id hysteria &>/dev/null; then
echo "• 运行用户: hysteria"
fi
echo ""
}
# 处理安装失败
handle_install_failure() {
echo ""
log_error "Hysteria2 安装失败"
echo ""
echo -e "${YELLOW}可能的原因和解决方案:${NC}"
echo ""
echo "1. 网络问题:"
echo " • 检查网络连接"
echo " • 检查防火墙设置"
echo " • 尝试使用代理"
echo ""
echo "2. 系统兼容性:"
echo " • 确认系统版本支持"
echo " • 检查系统架构 (amd64/arm64)"
echo ""
echo "3. 权限问题:"
echo " • 确认以 root 权限运行"
echo " • 检查 SELinux 设置"
echo ""
echo "4. 手动安装:"
echo " • 访问 https://github.com/apernet/hysteria"
echo " • 下载对应架构的二进制文件"
echo " • 手动配置系统服务"
echo ""
echo "如需帮助,请访问项目页面或提交 Issue"
echo ""
}
# 主安装函数
install_hysteria2() {
echo -e "${CYAN}=== Hysteria2 安装向导 ===${NC}"
echo ""
# 检查是否已安装
if command -v hysteria &> /dev/null; then
local version
version=$(hysteria version 2>/dev/null | head -1)
echo -e "${YELLOW}检测到已安装的 Hysteria2: ${version:-未知版本}${NC}"
echo ""
echo -n "是否重新安装? [y/N]: "
read -r reinstall
if [[ ! $reinstall =~ ^[Yy]$ ]]; then
log_info "取消安装"
return 0
fi
echo ""
log_info "将执行重新安装..."
# 备份现有配置
backup_existing_config
fi
# 执行安装前检查
log_info "执行安装前检查..."
echo ""
if ! check_system_compatibility; then
error_exit "系统兼容性检查失败"
fi
if ! check_required_commands; then
error_exit "必要命令检查失败"
fi
if ! check_network_connection; then
error_exit "网络连接检查失败"
fi
if ! check_port_usage; then
error_exit "端口检查失败"
fi
echo ""
log_success "所有检查通过,开始安装..."
echo ""
# 执行安装步骤
local install_success=true
# 步骤1: 安装二进制文件
if ! install_hysteria2_binary; then
install_success=false
fi
# 步骤2: 创建配置目录
if $install_success && ! create_config_directory; then
log_warn "配置目录创建失败,但继续安装"
fi
# 步骤3: 配置系统服务
if $install_success && ! configure_system_service; then
log_warn "系统服务配置失败,但继续安装"
fi
# 步骤4: 验证安装
if $install_success && ! verify_installation; then
install_success=false
fi
# 显示结果
echo ""
if $install_success; then
show_post_install_info
else
handle_install_failure
fi
echo ""
read -p "按回车键继续..." -r
return $([ $install_success = true ] && echo 0 || echo 1)
}
# 卸载函数 (如果需要在这里处理)
uninstall_hysteria2() {
log_info "卸载 Hysteria2..."
# 停止服务
if systemctl is-active --quiet hysteria-server; then
systemctl stop hysteria-server
log_info "已停止服务"
fi
# 禁用服务
if systemctl is-enabled --quiet hysteria-server 2>/dev/null; then
systemctl disable hysteria-server
log_info "已禁用服务"
fi
# 使用官方卸载方法
if curl -fsSL https://get.hy2.sh/ | bash -s -- --remove; then
log_success "Hysteria2 卸载成功"
else
log_error "卸载失败,请手动清理"
return 1
fi
return 0
}
# 如果脚本被直接运行
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
install_hysteria2
fi