添加 Alpine 支持
This commit is contained in:
272
hy2.sh
272
hy2.sh
@@ -3,10 +3,20 @@ set -Eeuo pipefail
|
|||||||
trap 'echo "[错误] 第 $LINENO 行执行失败:$BASH_COMMAND" >&2' ERR
|
trap 'echo "[错误] 第 $LINENO 行执行失败:$BASH_COMMAND" >&2' ERR
|
||||||
|
|
||||||
CONFIG_FILE="/etc/hysteria/config.yaml"
|
CONFIG_FILE="/etc/hysteria/config.yaml"
|
||||||
SERVICE_NAME="hysteria-server.service"
|
HYSTERIA_BIN="/usr/local/bin/hysteria"
|
||||||
|
HYSTERIA_WORK_DIR="/var/lib/hysteria"
|
||||||
|
SYSTEMD_SERVICE_NAME="hysteria-server.service"
|
||||||
|
OPENRC_SERVICE_NAME="hysteria-server"
|
||||||
|
OPENRC_SERVICE_FILE="/etc/init.d/${OPENRC_SERVICE_NAME}"
|
||||||
|
OPENRC_LOG_FILE="/var/log/${OPENRC_SERVICE_NAME}.log"
|
||||||
|
SERVICE_NAME="${SYSTEMD_SERVICE_NAME}"
|
||||||
DEVICE_USERS=(macminim4 iphone12p ipadmini5 pve_debian other)
|
DEVICE_USERS=(macminim4 iphone12p ipadmini5 pve_debian other)
|
||||||
USERPASS_ENTRIES=()
|
USERPASS_ENTRIES=()
|
||||||
TRAFFIC_STATS_SECRET=""
|
TRAFFIC_STATS_SECRET=""
|
||||||
|
PACKAGE_MANAGER=""
|
||||||
|
INIT_SYSTEM=""
|
||||||
|
OS_ID=""
|
||||||
|
OS_ID_LIKE=""
|
||||||
|
|
||||||
red() { printf '\033[31m%s\033[0m\n' "$*"; }
|
red() { printf '\033[31m%s\033[0m\n' "$*"; }
|
||||||
green() { printf '\033[32m%s\033[0m\n' "$*"; }
|
green() { printf '\033[32m%s\033[0m\n' "$*"; }
|
||||||
@@ -33,6 +43,70 @@ import json
|
|||||||
PY
|
PY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_systemd() {
|
||||||
|
[[ "${INIT_SYSTEM}" == "systemd" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_openrc() {
|
||||||
|
[[ "${INIT_SYSTEM}" == "openrc" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
load_os_release() {
|
||||||
|
if [[ -r /etc/os-release ]]; then
|
||||||
|
OS_ID="$(awk -F= '/^ID=/{gsub(/"/, "", $2); print $2; exit}' /etc/os-release)"
|
||||||
|
OS_ID_LIKE="$(awk -F= '/^ID_LIKE=/{gsub(/"/, "", $2); print $2; exit}' /etc/os-release)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_label() {
|
||||||
|
printf '%s/%s/%s' "${OS_ID:-unknown}" "${PACKAGE_MANAGER:-unknown}" "${INIT_SYSTEM:-unknown}"
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_platform() {
|
||||||
|
load_os_release
|
||||||
|
|
||||||
|
if command -v apk >/dev/null 2>&1 || [[ "${OS_ID}" == "alpine" ]] || [[ " ${OS_ID_LIKE} " == *" alpine "* ]]; then
|
||||||
|
PACKAGE_MANAGER="apk"
|
||||||
|
INIT_SYSTEM="openrc"
|
||||||
|
SERVICE_NAME="${OPENRC_SERVICE_NAME}"
|
||||||
|
if ! command -v rc-service >/dev/null 2>&1 || ! command -v rc-update >/dev/null 2>&1; then
|
||||||
|
red "检测到 Alpine/apk,但未发现 OpenRC(rc-service/rc-update),无法继续。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v apt >/dev/null 2>&1; then
|
||||||
|
PACKAGE_MANAGER="apt"
|
||||||
|
INIT_SYSTEM="systemd"
|
||||||
|
SERVICE_NAME="${SYSTEMD_SERVICE_NAME}"
|
||||||
|
if ! command -v systemctl >/dev/null 2>&1; then
|
||||||
|
red "检测到 APT 环境,但未发现 systemctl,当前脚本暂不支持该初始化系统。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
red "当前仅支持 Debian/Ubuntu(apt + systemd)和 Alpine(apk + OpenRC)。"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_hysteria_arch() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) echo "amd64" ;;
|
||||||
|
i386|i686) echo "386" ;;
|
||||||
|
armv5*|arm5*) echo "armv5" ;;
|
||||||
|
armv6*|armv7*|arm) echo "arm" ;;
|
||||||
|
aarch64|arm64) echo "arm64" ;;
|
||||||
|
s390x) echo "s390x" ;;
|
||||||
|
mips64le|mipsle|mips) echo "mipsle" ;;
|
||||||
|
riscv64) echo "riscv64" ;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
random_subdomain_prefix() {
|
random_subdomain_prefix() {
|
||||||
openssl rand -hex 8 | cut -c1-8
|
openssl rand -hex 8 | cut -c1-8
|
||||||
}
|
}
|
||||||
@@ -137,7 +211,7 @@ get_server_ip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apt_update_and_install_base() {
|
apt_update_and_install_base() {
|
||||||
if ! confirm_yn "即将执行 apt update 并安装基础依赖 curl sed ufw openssl python3,是否继续?"; then
|
if ! confirm_yn "即将执行 apt update 并安装基础依赖 curl sed ufw openssl python3 ca-certificates,是否继续?"; then
|
||||||
red "已取消。"
|
red "已取消。"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -150,7 +224,65 @@ apt_update_and_install_base() {
|
|||||||
|
|
||||||
blue "==> 安装基础依赖"
|
blue "==> 安装基础依赖"
|
||||||
wait_for_apt_lock 300 || { red "APT 被占用,无法继续。"; exit 1; }
|
wait_for_apt_lock 300 || { red "APT 被占用,无法继续。"; exit 1; }
|
||||||
apt install -y curl sed ufw openssl python3
|
apt install -y curl sed ufw openssl python3 ca-certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
apk_update_and_install_base() {
|
||||||
|
if ! confirm_yn "即将执行 apk update 并安装基础依赖 bash curl sed ufw ufw-openrc openssl python3 iptables ca-certificates,是否继续?"; then
|
||||||
|
red "已取消。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
blue "==> 更新 APK 软件索引"
|
||||||
|
apk update
|
||||||
|
|
||||||
|
blue "==> 安装基础依赖"
|
||||||
|
apk add --no-cache bash curl sed ufw ufw-openrc openssl python3 iptables ca-certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
install_base_dependencies() {
|
||||||
|
case "${PACKAGE_MANAGER}" in
|
||||||
|
apt) apt_update_and_install_base ;;
|
||||||
|
apk) apk_update_and_install_base ;;
|
||||||
|
*)
|
||||||
|
red "未知包管理器:${PACKAGE_MANAGER}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
service_exists() {
|
||||||
|
local service="$1"
|
||||||
|
|
||||||
|
if is_systemd; then
|
||||||
|
systemctl list-unit-files 2>/dev/null | grep -Eq "^${service}(\\.service)?"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_openrc; then
|
||||||
|
[[ -x "/etc/init.d/${service}" ]]
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_and_disable_service() {
|
||||||
|
local service="$1"
|
||||||
|
|
||||||
|
if is_systemd; then
|
||||||
|
systemctl stop "${service}" || true
|
||||||
|
systemctl disable "${service}" || true
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_openrc; then
|
||||||
|
rc-service "${service}" stop || true
|
||||||
|
rc-update del "${service}" default || true
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
disable_existing_firewalls() {
|
disable_existing_firewalls() {
|
||||||
@@ -165,19 +297,22 @@ disable_existing_firewalls() {
|
|||||||
yellow "检测到 UFW,正在关闭并重置"
|
yellow "检测到 UFW,正在关闭并重置"
|
||||||
ufw disable || true
|
ufw disable || true
|
||||||
yes | ufw reset || true
|
yes | ufw reset || true
|
||||||
|
if is_openrc && service_exists ufw; then
|
||||||
|
rc-service ufw stop || true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if systemctl list-unit-files 2>/dev/null | grep -q '^firewalld\.service'; then
|
if service_exists firewalld; then
|
||||||
yellow "检测到 firewalld,正在停止并禁用"
|
yellow "检测到 firewalld,正在停止并禁用"
|
||||||
systemctl stop firewalld || true
|
stop_and_disable_service firewalld || true
|
||||||
systemctl disable firewalld || true
|
if is_systemd; then
|
||||||
systemctl mask firewalld || true
|
systemctl mask firewalld || true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if systemctl list-unit-files 2>/dev/null | grep -q '^nftables\.service'; then
|
if service_exists nftables; then
|
||||||
yellow "检测到 nftables,正在停止并禁用"
|
yellow "检测到 nftables,正在停止并禁用"
|
||||||
systemctl stop nftables || true
|
stop_and_disable_service nftables || true
|
||||||
systemctl disable nftables || true
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command -v nft >/dev/null 2>&1; then
|
if command -v nft >/dev/null 2>&1; then
|
||||||
@@ -234,9 +369,62 @@ configure_ufw() {
|
|||||||
ufw allow 443/udp || true
|
ufw allow 443/udp || true
|
||||||
yes | ufw enable || true
|
yes | ufw enable || true
|
||||||
|
|
||||||
|
if is_openrc && service_exists ufw; then
|
||||||
|
rc-update add ufw default || true
|
||||||
|
rc-service ufw restart || rc-service ufw start || true
|
||||||
|
fi
|
||||||
|
|
||||||
green "UFW 配置完成。"
|
green "UFW 配置完成。"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_openrc_service_file() {
|
||||||
|
mkdir -p "${HYSTERIA_WORK_DIR}"
|
||||||
|
|
||||||
|
cat > "${OPENRC_SERVICE_FILE}" <<EOF
|
||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
description="Hysteria 2 server"
|
||||||
|
command="${HYSTERIA_BIN}"
|
||||||
|
command_args="server -c ${CONFIG_FILE}"
|
||||||
|
command_background="yes"
|
||||||
|
pidfile="/run/\${RC_SVCNAME}.pid"
|
||||||
|
start_stop_daemon_args="--chdir ${HYSTERIA_WORK_DIR} --stdout ${OPENRC_LOG_FILE} --stderr ${OPENRC_LOG_FILE}"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need net
|
||||||
|
use dns logger firewall
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
checkpath --directory --owner root:root --mode 0755 ${HYSTERIA_WORK_DIR}
|
||||||
|
checkpath --file --owner root:root --mode 0644 ${OPENRC_LOG_FILE}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 "${OPENRC_SERVICE_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_hysteria2_alpine() {
|
||||||
|
local arch download_url tmp_bin
|
||||||
|
|
||||||
|
arch="$(detect_hysteria_arch)" || {
|
||||||
|
red "当前架构 $(uname -m) 暂无对应的 Alpine 安装分支。"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
download_url="https://github.com/apernet/hysteria/releases/latest/download/hysteria-linux-${arch}"
|
||||||
|
tmp_bin="$(mktemp)"
|
||||||
|
|
||||||
|
blue "==> 下载 Hysteria 2 二进制 (${arch})"
|
||||||
|
curl -fsSL "${download_url}" -o "${tmp_bin}"
|
||||||
|
|
||||||
|
blue "==> 安装 Hysteria 2 二进制"
|
||||||
|
install -m 755 "${tmp_bin}" "${HYSTERIA_BIN}"
|
||||||
|
rm -f "${tmp_bin}"
|
||||||
|
|
||||||
|
write_openrc_service_file
|
||||||
|
}
|
||||||
|
|
||||||
install_hysteria2() {
|
install_hysteria2() {
|
||||||
if ! confirm_yn "即将安装 Hysteria 2,是否继续?"; then
|
if ! confirm_yn "即将安装 Hysteria 2,是否继续?"; then
|
||||||
red "已取消 Hysteria 2 安装。"
|
red "已取消 Hysteria 2 安装。"
|
||||||
@@ -244,7 +432,13 @@ install_hysteria2() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
blue "==> 安装 Hysteria 2"
|
blue "==> 安装 Hysteria 2"
|
||||||
bash <(curl -fsSL https://get.hy2.sh/)
|
|
||||||
|
if is_openrc; then
|
||||||
|
install_hysteria2_alpine
|
||||||
|
else
|
||||||
|
bash <(curl -fsSL https://get.hy2.sh/)
|
||||||
|
fi
|
||||||
|
|
||||||
green "Hysteria 2 安装完成。"
|
green "Hysteria 2 安装完成。"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,6 +584,13 @@ backup_existing_config() {
|
|||||||
set_config_permissions() {
|
set_config_permissions() {
|
||||||
local service_user service_group
|
local service_user service_group
|
||||||
|
|
||||||
|
if is_openrc; then
|
||||||
|
chown root:root "${CONFIG_FILE}"
|
||||||
|
chmod 600 "${CONFIG_FILE}"
|
||||||
|
green "已按 OpenRC 服务配置将配置文件权限设置为 root:root 600"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
service_user="$(systemctl show -p User --value "${SERVICE_NAME}" 2>/dev/null || true)"
|
service_user="$(systemctl show -p User --value "${SERVICE_NAME}" 2>/dev/null || true)"
|
||||||
service_user="${service_user//$'\n'/}"
|
service_user="${service_user//$'\n'/}"
|
||||||
|
|
||||||
@@ -525,12 +726,38 @@ start_service() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
blue "==> 启动并设置开机自启"
|
blue "==> 启动并设置开机自启"
|
||||||
systemctl daemon-reload || true
|
if is_systemd; then
|
||||||
systemctl enable --now "${SERVICE_NAME}"
|
systemctl daemon-reload || true
|
||||||
systemctl restart "${SERVICE_NAME}"
|
systemctl enable --now "${SERVICE_NAME}"
|
||||||
|
systemctl restart "${SERVICE_NAME}"
|
||||||
|
else
|
||||||
|
rc-update add "${SERVICE_NAME}" default || true
|
||||||
|
rc-service "${SERVICE_NAME}" restart || rc-service "${SERVICE_NAME}" start
|
||||||
|
fi
|
||||||
green "服务已启动。"
|
green "服务已启动。"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_service_status() {
|
||||||
|
if is_systemd; then
|
||||||
|
systemctl --no-pager --full status "${SERVICE_NAME}" || true
|
||||||
|
else
|
||||||
|
rc-service "${SERVICE_NAME}" status || true
|
||||||
|
pgrep -af "${HYSTERIA_BIN##*/}" || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
show_recent_logs() {
|
||||||
|
if is_systemd; then
|
||||||
|
journalctl --no-pager -n 30 -u "${SERVICE_NAME}" || true
|
||||||
|
else
|
||||||
|
if [[ -f "${OPENRC_LOG_FILE}" ]]; then
|
||||||
|
tail -n 30 "${OPENRC_LOG_FILE}" || true
|
||||||
|
else
|
||||||
|
yellow "暂未找到 OpenRC 日志文件:${OPENRC_LOG_FILE}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
show_result() {
|
show_result() {
|
||||||
local domain="$1"
|
local domain="$1"
|
||||||
local proxy_url="$2"
|
local proxy_url="$2"
|
||||||
@@ -544,6 +771,7 @@ show_result() {
|
|||||||
echo "域名: ${domain}"
|
echo "域名: ${domain}"
|
||||||
echo "端口: 443"
|
echo "端口: 443"
|
||||||
echo "认证方式: userpass"
|
echo "认证方式: userpass"
|
||||||
|
echo "服务管理器: ${INIT_SYSTEM}"
|
||||||
echo "伪装站点: ${proxy_url}"
|
echo "伪装站点: ${proxy_url}"
|
||||||
echo "流量统计监听: 127.0.0.1:9999"
|
echo "流量统计监听: 127.0.0.1:9999"
|
||||||
echo "流量统计密钥: ${TRAFFIC_STATS_SECRET}"
|
echo "流量统计密钥: ${TRAFFIC_STATS_SECRET}"
|
||||||
@@ -563,29 +791,35 @@ show_result() {
|
|||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
echo "hysteria 状态:"
|
echo "hysteria 状态:"
|
||||||
systemctl --no-pager --full status "${SERVICE_NAME}" || true
|
show_service_status
|
||||||
echo
|
echo
|
||||||
echo "最近日志:"
|
echo "最近日志:"
|
||||||
journalctl --no-pager -n 30 -u "${SERVICE_NAME}" || true
|
show_recent_logs
|
||||||
echo "================================================"
|
echo "================================================"
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
require_root
|
require_root
|
||||||
|
detect_platform
|
||||||
|
|
||||||
if ! confirm_yn "本脚本将更新软件源、关闭现有防火墙、配置 UFW、安装并配置 Hysteria 2,是否继续?"; then
|
if ! confirm_yn "本脚本将更新软件源、关闭现有防火墙、配置 UFW、安装并配置 Hysteria 2(检测到: $(platform_label)),是否继续?"; then
|
||||||
red "用户取消执行。"
|
red "用户取消执行。"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt_update_and_install_base
|
install_base_dependencies
|
||||||
|
|
||||||
require_cmd curl
|
require_cmd curl
|
||||||
require_cmd sed
|
require_cmd sed
|
||||||
require_cmd systemctl
|
|
||||||
require_cmd ufw
|
require_cmd ufw
|
||||||
require_cmd openssl
|
require_cmd openssl
|
||||||
require_cmd python3
|
require_cmd python3
|
||||||
|
if is_systemd; then
|
||||||
|
require_cmd systemctl
|
||||||
|
else
|
||||||
|
require_cmd rc-service
|
||||||
|
require_cmd rc-update
|
||||||
|
fi
|
||||||
require_python3_json || { red "python3 缺少 json 模块,无法解析 Cloudflare API 返回值。"; exit 1; }
|
require_python3_json || { red "python3 缺少 json 模块,无法解析 Cloudflare API 返回值。"; exit 1; }
|
||||||
|
|
||||||
local email zone subdomain default_subdomain proxy_url ip_info ipv4 ipv6 domain username
|
local email zone subdomain default_subdomain proxy_url ip_info ipv4 ipv6 domain username
|
||||||
|
|||||||
Reference in New Issue
Block a user