直播源 含优质9+9m3u
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
m3u/Pixman.sh

1431 lines
49 KiB

#!/bin/bash
###############################
# @小白直播搭建脚本
# 项目地址:https://pixman.io/
# 最新版本:1.9.6
###############################
# 设置路径
SCRIPT_PATH="$HOME/pixman.sh" # 定义脚本路径
CONFIG_FILE="$HOME/.pixman" # 配置文件路径
# 设置默认环境变量
REVERSE_PROXY="dockerpull.com" # 设置反向代理地址
CRON_SCHEDULE="0 12 * * *" # 默认定时任务时间
PORT="52055" # 默认端口
MYTVSUPER_TOKEN="" # myTV 参数
HAMI_SESSION_ID="" # Hami 参数
HAMI_SERIAL_NO="" # Hami 参数
HAMI_SESSION_IP="" # Hami 参数
HTTP_PROXY="" # 设置代理
HTTPS_PROXY="" # 设置代理
# 设置颜色变量
RED="\033[1;31m" # 红
GREEN="\033[1;32m" # 绿
YELLOW="\033[1;33m" # 黄
CYAN="\033[1;36m" # 青
RESET="\033[0m" # 重置
# echo -e "${CYAN}这是绿色粗体文本。${RESET}"
############# 菜单 #############
# 显示 菜单
show_menu() {
echo "-------------------"
echo " @小白直播搭建工具 "
echo " 输入 y 快捷启动 "
echo "-------------------"
echo " 请选择一个项目: "
echo "-------------------"
echo "1) Pixman 项目 "
echo "2) Allinone 项目 "
echo "~~~~~~~~~~~~~~~~~~~"
echo "3) -- 工具箱 -- "
echo "~~~~~~~~~~~~~~~~~~~"
echo "4) ~~ 脚本信息 ~~ "
echo "-------------------"
echo "0) 退出 "
echo " [ Ctrl+C ] "
echo "-------------------"
}
# Pixman 菜单
show_pixman_menu() {
echo "-------------------"
echo " Pixman 菜单: "
echo "-------------------"
echo "1) 安装 Pixman 项目"
echo "2) 修改 Pixman 参数"
echo "3) 生成 Pixman 订阅"
echo "4) 转换 myTV 订阅"
echo "5) 卸载 Pixman 项目"
echo "-------------------"
echo "0) 返回主菜单 "
echo "-------------------"
}
# allinone 菜单
show_allinone_menu() {
echo "---------------------"
echo " Allinone 菜单: "
echo "---------------------"
echo "1) 安装 Allinone 项目"
echo "2) 安装 av3a 助手"
echo "3) 设置 反向代理 地址 "
echo "4) 卸载 Allinone 项目"
echo "---------------------"
echo "0) 返回主菜单 "
echo "---------------------"
}
# 工具箱 菜单
show_toolbox_menu() {
echo "----------------------"
echo " 工具箱菜单: "
echo "----------------------"
echo "1) 1Panle 面板 "
echo "2) [Docker] o11 "
echo "3) [Docker] 3X-UI "
echo "~~~~~~~~~~~~~~~~~~~~~~"
echo "5) Docker 一键清理 "
echo "----------------------"
echo "0) 返回主菜单 "
echo "----------------------"
}
# 1Panel 菜单
show_1panel_menu() {
echo "-------------------"
echo " 1Panel 菜单: "
echo "-------------------"
echo "1) 安装 1Panel "
echo "2) 卸载 1Panel "
echo "3) 设置 1Panel "
echo "-------------------"
echo "0) 返回上级菜单 "
echo "-------------------"
}
# 3X-UI 菜单
show_3x_ui_menu() {
echo "-------------------"
echo " 3X-UI 菜单: "
echo "-------------------"
echo "1) 安装 3X-UI "
echo "2) 更新 3X-UI "
echo "3) 卸载 3X-UI "
echo "-------------------"
echo "0) 返回上级菜单 "
echo "-------------------"
}
# o11 菜单
show_o11_menu() {
echo "-------------------"
echo " o11 菜单: "
echo "-------------------"
echo "1) 安装 o11 "
echo "2) 卸载 o11 "
echo "-------------------"
echo "0) 返回上级菜单 "
echo "-------------------"
}
# subs 菜单
show_subs_menu() {
echo "-------------------"
echo " Sub Store 菜单: "
echo "-------------------"
echo "1) 安装 Sub Store "
echo "2) 卸载 Sub Store "
echo "-------------------"
echo "0) 返回上级菜单 "
echo "-------------------"
}
############# Pixman #############
# 加载 Pixman 参数
load_parameters() {
if [ -e "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
else
if docker ps -a --format '{{.Names}}' | grep -q "^pixman$"; then
check_and_install_jq
extract_container_parameters
source "$CONFIG_FILE"
else
return 1
fi
fi
}
# 提取 Pixman 参数
extract_container_parameters() {
container_info=$(docker inspect "pixman")
PORT=$(echo "$container_info" | jq -r '.[0].HostConfig.PortBindings."5000/tcp"[0].HostPort // empty')
if [ -z "$PORT" ]; then
PORT=5000
fi
MYTVSUPER_TOKEN=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("MYTVSUPER_TOKEN="))' | cut -d= -f2)
HAMI_SESSION_ID=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("HAMI_SESSION_ID="))' | cut -d= -f2)
HAMI_SERIAL_NO=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("HAMI_SERIAL_NO="))' | cut -d= -f2)
HAMI_SESSION_IP=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("HAMI_SESSION_IP="))' | cut -d= -f2)
HTTP_PROXY=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("HTTP_PROXY="))' | cut -d= -f2)
HTTPS_PROXY=$(echo "$container_info" | jq -r '.[0].Config.Env[] | select(startswith("HTTPS_PROXY="))' | cut -d= -f2)
echo "PORT=$PORT" > "$CONFIG_FILE"
echo "MYTVSUPER_TOKEN=$MYTVSUPER_TOKEN" >> "$CONFIG_FILE"
echo "HAMI_SESSION_ID=$HAMI_SESSION_ID" >> "$CONFIG_FILE"
echo "HAMI_SERIAL_NO=$HAMI_SERIAL_NO" >> "$CONFIG_FILE"
echo "HAMI_SESSION_IP=$HAMI_SESSION_IP" >> "$CONFIG_FILE"
echo "HTTP_PROXY=$HTTP_PROXY" >> "$CONFIG_FILE"
echo "HTTPS_PROXY=$HTTPS_PROXY" >> "$CONFIG_FILE"
}
# 保存 Pixman 参数
save_parameters() {
{
echo "REVERSE_PROXY=$REVERSE_PROXY"
echo "SCRIPT_PATH=$SCRIPT_PATH"
[ -n "$PORT" ] && echo "PORT=$PORT"
[ -n "$CRON_SCHEDULE" ] && echo "CRON_SCHEDULE=$CRON_SCHEDULE"
[ -n "$MYTVSUPER_TOKEN" ] && echo "MYTVSUPER_TOKEN=$MYTVSUPER_TOKEN"
[ -n "$HAMI_SESSION_ID" ] && echo "HAMI_SESSION_ID=$HAMI_SESSION_ID"
[ -n "$HAMI_SERIAL_NO" ] && echo "HAMI_SERIAL_NO=$HAMI_SERIAL_NO"
[ -n "$HAMI_SESSION_IP" ] && echo "HAMI_SESSION_IP=$HAMI_SESSION_IP"
[ -n "$HTTP_PROXY" ] && echo "HTTP_PROXY=$HTTP_PROXY"
[ -n "$HTTPS_PROXY" ] && echo "HTTPS_PROXY=$HTTPS_PROXY"
} > "$CONFIG_FILE"
}
# 设置 Pixman 参数
set_parameters() {
local original_port="$PORT"
local original_token="$MYTVSUPER_TOKEN"
local original_session_id="$HAMI_SESSION_ID"
local original_serial_no="$HAMI_SERIAL_NO"
local original_session_ip="$HAMI_SESSION_IP"
local original_http_proxy="$HTTP_PROXY"
local original_https_proxy="$HTTPS_PROXY"
read -p "请输入反向代理地址 (回车跳过保持当前值: $REVERSE_PROXY): " input_reverse_proxy
[ -n "$input_reverse_proxy" ] && REVERSE_PROXY="$input_reverse_proxy"
read -p "请确认脚本路径 (回车跳过保持当前值: $SCRIPT_PATH): " input_path
[ -n "$input_path" ] && SCRIPT_PATH="$input_path"
read -p "请输入定时任务时间 (cron格式,回车跳过保持当前值: $CRON_SCHEDULE): " input_cron
[ -n "$input_cron" ] && CRON_SCHEDULE="$input_cron"
read -p "请输入端口 (回车跳过保持当前值: $PORT): " input_port
[ -n "$input_port" ] && PORT="$input_port"
read -p "请输入 MYTVSUPER_TOKEN (回车跳过保持当前值: $MYTVSUPER_TOKEN): " input_token
[ -n "$input_token" ] && MYTVSUPER_TOKEN="$input_token"
read -p "请输入 HAMI_SESSION_ID (回车跳过保持当前值: $HAMI_SESSION_ID): " input_id
[ -n "$input_id" ] && HAMI_SESSION_ID="$input_id"
read -p "请输入 HAMI_SERIAL_NO (回车跳过保持当前值: $HAMI_SERIAL_NO): " input_serial
[ -n "$input_serial" ] && HAMI_SERIAL_NO="$input_serial"
read -p "请输入 HAMI_SESSION_IP (回车跳过保持当前值: $HAMI_SESSION_IP): " input_ip
[ -n "$input_ip" ] && HAMI_SESSION_IP="$input_ip"
read -p "请输入 HTTP_PROXY (回车跳过保持当前值: $HTTP_PROXY): " input_http_proxy
[ -n "$input_http_proxy" ] && HTTP_PROXY="$input_http_proxy"
read -p "请输入 HTTPS_PROXY (回车跳过保持当前值: $HTTPS_PROXY): " input_https_proxy
[ -n "$input_https_proxy" ] && HTTPS_PROXY="$input_https_proxy"
save_parameters
if [[ "$PORT" != "$original_port" || \
"$MYTVSUPER_TOKEN" != "$original_token" || \
"$HAMI_SESSION_ID" != "$original_session_id" || \
"$HAMI_SERIAL_NO" != "$original_serial_no" || \
"$HAMI_SESSION_IP" != "$original_session_ip" || \
"$HTTP_PROXY" != "$original_http_proxy" || \
"$HTTPS_PROXY" != "$original_https_proxy" ]]; then
echo -e "${CYAN}检测到参数变化,正在卸载旧的 Pixman 容器...${RESET}"
docker rm -f pixman > /dev/null 2>&1
check_update
else
echo -e "${CYAN}参数未发生变化,无需重启 Pixman 容器${RESET}"
return 0
fi
}
# 设置 Pixman 自动更新
set_cron_job() {
(crontab -l 2>/dev/null | grep -v "$SCRIPT_PATH --auto"; echo "$CRON_SCHEDULE $SCRIPT_PATH --auto") | crontab -
}
# 判断 Pixman 容器
check_update() {
echo -e "${CYAN}检查更新...${RESET}"
IMAGE_SOURCE="pixman/pixman:latest"
PROXY_IMAGE_SOURCE="$REVERSE_PROXY/pixman/pixman:latest"
if docker ps -a --format '{{.Names}}' | grep -q "^pixman$"; then
current_image_version=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' pixman)
MODE=$(docker inspect --format='{{.HostConfig.NetworkMode}}' pixman)
if ! docker pull "$IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${CYAN}尝试使用代理...${RESET}"
if ! docker pull "$PROXY_IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${RED}安装 Pixman 失败,请检查代理或网络连接。${RESET}"
exit 1
fi
IMAGE_SOURCE="$PROXY_IMAGE_SOURCE"
fi
latest_image_version=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$IMAGE_SOURCE")
if [ "$current_image_version" != "$latest_image_version" ]; then
echo -e "${GREEN}发现新版本 ($latest_image_version),正在更新...${RESET}"
docker rm -f pixman > /dev/null 2>&1
docker rmi -f "$IMAGE_SOURCE" > /dev/null 2>&1
docker pull "$IMAGE_SOURCE" > /dev/null 2>&1
start_container "$IMAGE_SOURCE" "$MODE"
else
echo -e "${GREEN}当前版本 ($current_image_version),无需更新...${RESET}"
fi
else
if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^pixman/pixman:latest$"; then
if ! docker pull "$IMAGE_SOURCE" > /dev/null 2>&1; then
echo "尝试使用代理..."
if ! docker pull "$PROXY_IMAGE_SOURCE" > /dev/null 2>&1; then
echo "使用代理拉取失败,请检查代理或网络连接。"
return 1
fi
latest_image_version=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$IMAGE_SOURCE")
echo -e "${GREEN}目前版本 ($latest_image_version),正在安装...${RESET}"
IMAGE_SOURCE="$PROXY_IMAGE_SOURCE"
fi
fi
start_container "$IMAGE_SOURCE"
fi
}
# 部署 Pixman 容器
start_container() {
local image_source="$1"
local mode="$2"
local port="${PORT:-52055}"
echo -e "${CYAN}启动 Pixman 容器...${RESET}"
if [ "$mode" != "bridge" ] && [ "$mode" != "host" ]; then
echo "请选择 Docker 模式:"
echo "1. Bridge 模式 (默认)"
echo "2. Host 模式"
read -p "输入选择 [1/2]: " user_choice
mode="bridge"
[[ "$user_choice" == "2" ]] && mode="host"
fi
if [[ "$mode" == "host" ]]; then
echo "目前使用 host 模式,默认端口: 5000。"
docker_command="docker run -d --name pixman --restart always --net=host"
else
echo "目前使用 bridge 模式,默认端口: $port"
docker_command="docker run -d --name pixman --restart always -p $port:5000"
fi
[ -n "$MYTVSUPER_TOKEN" ] && docker_command+=" -e MYTVSUPER_TOKEN=$MYTVSUPER_TOKEN"
[ -n "$HAMI_SESSION_ID" ] && docker_command+=" -e HAMI_SESSION_ID=$HAMI_SESSION_ID"
[ -n "$HAMI_SERIAL_NO" ] && docker_command+=" -e HAMI_SERIAL_NO=$HAMI_SERIAL_NO"
[ -n "$HAMI_SESSION_IP" ] && docker_command+=" -e HAMI_SESSION_IP=$HAMI_SESSION_IP"
[ -n "$HTTP_PROXY" ] && docker_command+=" -e HTTP_PROXY=$HTTP_PROXY"
[ -n "$HTTPS_PROXY" ] && docker_command+=" -e HTTPS_PROXY=$HTTPS_PROXY"
docker_command+=" $image_source"
eval "$docker_command"
echo -e "${GREEN}Pixman 容器已启动。${RESET}"
}
# 卸载 Pixman 项目
uninstall_pixman() {
echo "是否确定要卸载 Pixman 项目?[y/n]"
read -r -t 10 input
input=${input:-n}
if [[ "$input" =~ ^[Yy]$ ]]; then
echo -e "${CYAN}正在卸载 Pixman 项目...${RESET}"
docker stop pixman > /dev/null 2>&1
docker rm -f pixman > /dev/null 2>&1
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'pixman/pixman'); do
docker rmi "$image" > /dev/null 2>&1
done
crontab -l | grep -v "$SCRIPT_PATH"
# rm -f "$SCRIPT_PATH"
# rm -f "$CONFIG_FILE"
# sed -i '/alias y=/d' ~/.bashrc
echo -e "${RED}Pixman 项目已成功卸载。${RESET}"
else
echo -e "${GREEN}取消卸载操作。${RESET}"
fi
}
# 生成 Pixman 订阅
live_pixman() {
local public_ip
local port
local container_id
container_id=$(docker ps -aq -f name=pixman 2>/dev/null)
if [ -z "$container_id" ]; then
echo -e "${RED}错误: Pixman 容器不存在。${RESET}"
return 1
fi
MODE=$(docker inspect --format='{{.HostConfig.NetworkMode}}' pixman)
if [[ "$MODE" == "host" ]]; then
port=5000
else
port=$(docker inspect -f '{{ (index (index .HostConfig.PortBindings "5000/tcp") 0).HostPort }}' pixman 2>/dev/null)
fi
if check_if_in_china; then
public_ip="{路由IP}"
else
public_ip=$(curl -s ifconfig.me || echo "{公网IP}")
fi
parse_cron_schedule "$CRON_SCHEDULE"
echo "■ 央视频 YSP : http://${public_ip}:${port}/ysp.m3u"
echo "■ 江苏移动魔百盒 TPTV : http://${public_ip}:${port}/tptv.m3u 或 http://${public_ip}:${port}/tptv_proxy.m3u"
echo "■ 中国移动 iTV : http://${public_ip}:${port}/itv.m3u 或 http://${public_ip}:${port}/itv_proxy.m3u"
if check_internet_connection; then
echo "■ YouTube 代理 : http://${public_ip}:${port}/youtube/{VIDEO_ID} (房间号)"
echo "■ 四季線上 4GTV : http://${public_ip}:${port}/4gtv.m3u"
if [ -n "$MYTVSUPER_TOKEN" ]; then
echo "■ MytvSuper : http://${public_ip}:${port}/mytvsuper.m3u"
fi
if [ -n "$HAMI_SESSION_ID" ] && [ -n "$HAMI_SERIAL_NO" ] && [ -n "$HAMI_SESSION_IP" ]; then
echo "■ Hami Video : http://${public_ip}:${port}/hami.m3u"
fi
fi
echo "■ Beesport : http://${public_ip}:${port}/beesport.m3u"
echo "■ TheTV : http://${public_ip}:${port}/thetv.m3u"
echo "■ DLHD : http://${public_ip}:${port}/dlhd.m3u"
echo "---------------------------------------------------------"
echo "--- Pixman 详细使用说明: https://pixman.io/topics/17 ---"
echo "--- Pixman.sh 脚本日志: https://pixman.io/topics/142 ---"
echo "---------------------------------------------------------"
read -p "按 回车键 返回 主菜单 ..."
}
# 生成 myTV 订阅
Convert_pixman() {
local public_ip
local port
local container_id
container_id=$(docker ps -aq -f name=pixman 2>/dev/null)
if [ -z "$container_id" ]; then
echo -e "${RED}错误: Pixman 容器不存在。${RESET}"
return 1
fi
if [ -n "$MYTVSUPER_TOKEN" ]; then
if ping -c 1 google.com > /dev/null 2>&1; then
MODE=$(docker inspect --format='{{.HostConfig.NetworkMode}}' pixman)
if [[ "$MODE" == "host" ]]; then
port=5000
else
port=$(docker inspect -f '{{ (index (index .HostConfig.PortBindings "5000/tcp") 0).HostPort }}' pixman 2>/dev/null)
fi
if check_if_in_china; then
public_ip="{路由IP}"
else
public_ip=$(curl -s ifconfig.me || echo "{公网IP}")
fi
echo "生成订阅中..."
docker exec pixman sh -c 'flask mytvsuper_tivimate'
echo "---------------------------------------------------------"
echo "■ MytvSuper-tivimate : http://${public_ip}:${port}/mytvsuper-tivimate.m3u"
(crontab -l; echo "0 */12 * * * /usr/bin/docker exec pixman sh -c 'flask mytvsuper_tivimate'") | crontab -
echo "■ 定时任务已设置,每 12 小时自动更新 M3U。"
else
echo -e "${RED}请查看网络环境,目前已禁用 myTV 服务。${RESET}"
return 1
fi
else
echo -e "${CYAN}MYTVSUPER_TOKEN 参数不能为空,无法生成订阅。${RESET}"
return 1
fi
echo "---------------------------------------------------------"
echo "--- Pixman 详细使用说明: https://pixman.io/topics/17 ---"
echo "--- Pixman.sh 脚本日志: https://pixman.io/topics/142 ---"
echo "---------------------------------------------------------"
read -p "按 回车键 返回 主菜单 ..."
}
############# Allinone #############
# 安装 Allinone
install_allinone() {
if docker ps -a --format '{{.Names}}' | grep -q "^allinone$"; then
echo "检测到已存在的 Allinone 容器,将进行手动更新..."
docker stop allinone > /dev/null 2>&1
docker rm allinone > /dev/null 2>&1
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'youshandefeiyang/allinone'); do
docker rmi "$image" > /dev/null 2>&1
done
echo -e "${CYAN}已停止并删除旧的 Allinone 项目。${RESET}"
fi
echo "请选择部署方式(默认: 1):"
echo "1) 使用 host 网络模式"
echo "2) 使用 bridge 网络模式"
read -rp "输入选项 (1 或 2): " option
option=${option:-1}
local public_ip
local PORT=35455
if check_if_in_china; then
public_ip="{路由IP}"
else
public_ip=$(curl -s ifconfig.me || echo "{公网IP}")
fi
IMAGE_SOURCE="youshandefeiyang/allinone"
PROXY_IMAGE_SOURCE="$REVERSE_PROXY/youshandefeiyang/allinone"
if ! docker pull "$IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${CYAN}尝试使用代理拉取镜像...${RESET}"
if ! docker pull "$PROXY_IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${RED}安装 Allinone 失败,请检查代理或网络连接。${RESET}"
exit 1
fi
IMAGE_SOURCE="$PROXY_IMAGE_SOURCE"
fi
case $option in
1)
echo "正在使用 host 网络模式安装 Allinone..."
port=$PORT
docker run -d --restart unless-stopped --net=host --privileged=true --name allinone "$IMAGE_SOURCE"
echo -e "${GREEN}Allinone 安装完成。${RESET}"
install_watchtower "allinone"
echo "---------------------------------------------------------"
echo "■ 订阅地址:"
if check_if_in_china; then
echo "■ TV 集合 : http://$public_ip:$port/tv.m3u"
echo "■ TPTV : http://$public_ip:$port/tptv.m3u"
fi
;;
2)
echo "正在使用 bridge 网络模式安装 Allinone..."
read -rp "请输入要映射的端口 (默认: $PORT): " port
port=${port:-$PORT}
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1024 ] || [ "$port" -gt 65535 ]; then
echo "无效端口。请使用 1024 到 65535 之间的数字。"
return 1
fi
docker run -d --restart unless-stopped --net=bridge --privileged=true -p "$port:35455" --name allinone "$IMAGE_SOURCE"
echo -e "${GREEN}Allinone 安装完成。${RESET}"
install_watchtower "allinone"
echo "---------------------------------------------------------"
echo "■ 订阅地址:"
if check_if_in_china; then
echo "■ TV 集合 : http://$public_ip:$port/tv.m3u"
echo "■ TPTV : http://$public_ip:$port/tptv.m3u"
fi
;;
*)
echo -e "${CYAN}无效选项,请选择 1 或 2。${RESET}"
return 1
;;
esac
live_allinone "$public_ip" "$port"
}
# 生成 Allinone 订阅
live_allinone() {
local public_ip="$1"
local PORT="$2"
echo "■ YY轮播 : http://${public_ip}:${PORT}/yylunbo.m3u"
echo "■ BiliBili生活 : http://${public_ip}:${PORT}/bililive.m3u"
echo "■ 虎牙一起看 : http://${public_ip}:${PORT}/huyayqk.m3u"
echo "■ 斗鱼一起看 : http://${public_ip}:${PORT}/douyuyqk.m3u"
echo "---------------------------------------------------------"
echo "■ 代理地址:"
echo "■ BiliBili 代理 : http://${public_ip}:${PORT}/bilibili/{VIDEO_ID}"
echo "■ 虎牙 代理 : http://${public_ip}:${PORT}/huya/{VIDEO_ID}"
echo "■ 斗鱼 代理 : http://${public_ip}:${PORT}/douyu/{VIDEO_ID}"
echo "■ YY 代理 : http://${public_ip}:${PORT}/yy/{VIDEO_ID}"
echo "■ 抖音 代理 : http://${public_ip}:${PORT}/douyin/{VIDEO_ID}"
echo "■ YouTube 代理 : http://${public_ip}:${PORT}/youtube/{VIDEO_ID}"
echo "---------------------------------------------------------"
echo "--- allinone 详细使用说明: https://yycx.eu.org ---"
echo "--- Pixman.sh 脚本日志: https://pixman.io/topics/142 ---"
echo "---------------------------------------------------------"
read -p "按 回车键 返回 主菜单 ..."
}
# 设置反向代理参数
proxy_allinone() {
read -p "请输入反向代理地址 (回车跳过保持当前值: $REVERSE_PROXY): " input_reverse_proxy
[ -n "$input_reverse_proxy" ] && REVERSE_PROXY="$input_reverse_proxy"
echo "反向代理地址已更新为: $REVERSE_PROXY"
save_parameters
}
# 卸载 Allinone
uninstall_allinone() {
read -p "您确定要卸载 Allinone 及删除所有相关文件吗?(y/n): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "卸载操作已取消。"
return
fi
if docker ps -a | grep -q allinone; then
docker stop allinone > /dev/null 2>&1
docker rm allinone > /dev/null 2>&1
fi
if docker ps -a | grep -q av3a-assistant; then
docker stop av3a-assistant > /dev/null 2>&1
docker rm av3a-assistant > /dev/null 2>&1
fi
if [ -d "/av3a" ]; then
rm -rf /av3a
fi
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'youshandefeiyang/allinone'); do
docker rmi "$image" > /dev/null 2>&1
done
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'av3a-assistant'); do
docker rmi "$image" > /dev/null 2>&1
done
echo -e "${GREEN}Allinone 及其所有相关文件已完全卸载。${RESET}"
}
# 检查 Docker Compose 是否安装
install_Docker_Compose() {
if ! command -v docker-compose &> /dev/null; then
echo "Docker Compose 未安装,正在尝试安装..."
sudo curl -L "https://ghproxy.cc/https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
if ! command -v docker-compose &> /dev/null; then
echo "Docker Compose 安装失败,请手动安装。"
echo "参考资料:https://blog.csdn.net/Jimu2018/article/details/138325666"
exit 1
fi
echo -e "${GREEN}Docker Compose 安装完成。${RESET}"
else
echo -e "${GREEN}Docker Compose 已安装。${RESET}"
fi
}
# 安装 av3a
install_av3a() {
if ! check_if_in_china; then
echo -e "${RED}境外已禁止开启 av3a 服务。${RESET}"
return
fi
local public_ip="{路由IP}"
local PORT=35455
echo "若安装 av3a 助手,将固定端口,并删除 Allinone 部署,且 Docker 空间建议预留 3G 以上。"
read -p "是否继续安装 (y/n,默认 n): " CONFIRM_INSTALL
CONFIRM_INSTALL=${CONFIRM_INSTALL:-n}
if [[ "$CONFIRM_INSTALL" != "y" ]]; then
echo "安装已被终止。"
return
fi
if docker ps -a --format '{{.Names}}' | grep -q "av3a-assistant"; then
echo "av3a-assistant 容器已安装,跳过安装步骤。"
return
fi
install_Docker_Compose
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" || "$ARCH" == "amd64" ]]; then
echo "系统架构: amd64/x86_64"
INSTALL_PATH="/av3a"
generate_docker_compose "amd64" "$INSTALL_PATH"
elif [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
echo "系统架构: arm64/aarch64"
INSTALL_PATH="/av3a"
generate_docker_compose "arm64" "$INSTALL_PATH"
else
echo "不支持的系统架构: $ARCH,av3a 安装失败..."
return
fi
if docker ps -a --format '{{.Names}}' | grep -q '^allinone$'; then
echo "检测到已存在的 allinone 容器,正在停止并删除..."
docker stop allinone > /dev/null 2>&1
docker rm allinone > /dev/null 2>&1
fi
if generate_docker_compose "$ARCH" "$INSTALL_PATH"; then
cd "$INSTALL_PATH"
if docker-compose up -d; then
echo "---------------------------------------------------------"
echo -e "${GREEN}Allinone 和 av3a-assistant 均已安装${RESET}"
echo "---------------------------------------------------------"
echo "■ 订阅地址:"
echo "■ TV 集合 : http://$public_ip:35442/tv.m3u (av3a)"
echo "■ TV 集合 : http://$public_ip:35455/tv.m3u (原版)"
echo "■ TPTV : http://$public_ip:35455/tptv.m3u"
live_allinone "$public_ip" "$PORT"
else
echo "启动 Docker 容器失败。"
exit 1
fi
else
echo "生成 Docker Compose 文件失败,后续操作将被终止。"
exit 1
fi
}
# 生成 Docker Compose 文件
generate_docker_compose() {
local arch=$1
local install_path=$2
mkdir -p "$install_path" || { echo "无法创建目录 $install_path"; return 1; }
if [[ "$arch" == "x86_64" || "$arch" == "amd64" ]]; then
cat <<EOF > "$install_path/docker-compose.yml"
services:
av3a-assistant:
image: ${REVERSE_PROXY}/youshandefeiyang/av3a-assistant:amd64
container_name: av3a-assistant
privileged: true
restart: unless-stopped
ports:
- "35442:35442"
networks:
- my-network
allinone:
image: ${REVERSE_PROXY}/youshandefeiyang/allinone
container_name: allinone
privileged: true
restart: unless-stopped
ports:
- "35455:35455"
networks:
- my-network
networks:
my-network:
driver: bridge
EOF
elif [[ "$arch" == "aarch64" || "$arch" == "arm64" ]]; then
cat <<EOF > "$install_path/docker-compose.yml"
services:
av3a-assistant:
image: ${REVERSE_PROXY}/youshandefeiyang/av3a-assistant:arm64
container_name: av3a-assistant
privileged: true
restart: unless-stopped
ports:
- "35442:35442"
networks:
- my-network
allinone:
image: ${REVERSE_PROXY}/youshandefeiyang/allinone
container_name: allinone
privileged: true
restart: unless-stopped
ports:
- "35455:35455"
networks:
- my-network
networks:
my-network:
driver: bridge
EOF
else
echo "不支持的系统架构: $arch"
return 1
fi
}
############# watchtower #############
# 设置 watchtower 任务
install_watchtower() {
local name=$1
if [ "$(docker ps -q -f name=watchtower)" ]; then
existing_args=$(docker inspect --format '{{.Args}}' watchtower)
monitored_containers=$(echo "$existing_args" | grep -oP '(\w+)' | tr '\n' ' ')
if echo "$monitored_containers" | grep -qw "$name"; then
echo "---------------------------------------------------------"
echo -e "${CYAN}■ 服务器将于每天凌晨五点,进行检测更新。${RESET}"
return
fi
monitored_containers+="$name"
docker stop watchtower > /dev/null 2>&1
docker rm watchtower > /dev/null 2>&1
else
monitored_containers="$name"
fi
echo "正在安装或配置 Watchtower 并监控 $name 镜像更新..."
IMAGE_SOURCE="containrrr/watchtower"
PROXY_IMAGE_SOURCE="$REVERSE_PROXY/containrrr/watchtower"
if ! docker pull "$IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${CYAN}尝试使用代理拉取镜像...${RESET}"
if ! docker pull "$PROXY_IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${RED}安装 watchtower 失败,请检查代理或网络连接。${RESET}"
return
fi
IMAGE_SOURCE="$PROXY_IMAGE_SOURCE"
fi
docker run -d --name watchtower --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock "$IMAGE_SOURCE" $monitored_containers -c --schedule "0 5 * * *"
echo "---------------------------------------------------------"
echo -e "${CYAN}■ 服务器将于每天凌晨五点,进行检测更新。${RESET}"
}
# 卸载 Watchtower 监控指定容器
uninstall_watchtower() {
local name=$1
if [ "$(docker ps -q -f name=watchtower)" ]; then
echo "正在检查 Watchtower 监控的容器..."
existing_args=$(docker inspect --format '{{.Args}}' watchtower)
monitored_containers=$(echo "$existing_args" | grep -oP '(\w+)' | tr '\n' ' ')
if echo "$monitored_containers" | grep -qw "$name"; then
monitored_containers=$(echo "$monitored_containers" | sed "s/\b$name\b//g")
if [ -z "$monitored_containers" ]; then
echo "没有其他监控的容器,正在停止并删除 Watchtower..."
docker stop watchtower > /dev/null 2>&1
docker rm watchtower > /dev/null 2>&1
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'containrrr/watchtower'); do
docker rmi "$image" > /dev/null 2>&1
done
echo "Watchtower 已成功卸载。"
else
docker stop watchtower > /dev/null 2>&1
docker rm watchtower > /dev/null 2>&1
echo "正在更新 Watchtower,仅监控剩余容器..."
IMAGE_SOURCE="containrrr/watchtower"
PROXY_IMAGE_SOURCE="$REVERSE_PROXY/containrrr/watchtower"
if ! docker pull "$IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${CYAN}尝试使用代理拉取镜像...${RESET}"
if ! docker pull "$PROXY_IMAGE_SOURCE" > /dev/null 2>&1; then
echo -e "${RED}安装 watchtower 失败,请检查代理或网络连接。${RESET}"
return
fi
IMAGE_SOURCE="$PROXY_IMAGE_SOURCE"
fi
docker run -d --name watchtower --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock "$IMAGE_SOURCE" $monitored_containers -c --schedule "0 5 * * *"
echo "· "$name" 容器已从监控中删除。"
fi
else
echo "容器 $name 未被 Watchtower 监控。"
fi
else
echo "Watchtower 当前未安装。"
fi
}
############# 3X-UI #############
# 安装 3X-UI
install_3x_ui() {
echo "请选择部署方式:"
echo "1) 使用 host 网络模式 (添加节点方便)"
echo "2) 使用 bridge 网络模式 (添加节点,需映射端口)"
echo "3) 使用 sh 脚本 直接安装 (推荐)"
read -rp "输入选项 (1-3): " option
if check_if_in_china; then
local public_ip="{路由IP}"
else
local public_ip=$(curl -s ifconfig.me || echo "{公网IP}")
fi
case $option in
1)
echo "正在使用 host 网络模式安装 3X-UI 面板..."
docker run -d \
-e XRAY_VMESS_AEAD_FORCED=false \
-v "$PWD/db/:/etc/x-ui/" \
-v "$PWD/cert/:/root/cert/" \
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
echo -e "${GREEN}3X-UI 安装完成。${RESET}"
echo "访问信息:"
echo "URL: http://$public_ip:2053"
;;
2)
echo "正在使用 bridge 网络模式安装 3X-UI 面板..."
local default_port=17878
read -rp "请输入要映射的端口 (默认: $default_port): " port
port=${port:-$default_port}
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1024 ] || [ "$port" -gt 65535 ]; then
echo "无效端口。请使用 1024 到 65535 之间的数字。"
return 1
fi
local node_port1=$(generate_random_port)
local node_port2=$(generate_random_port)
local node_port3=$(generate_random_port)
docker run -d \
-e XRAY_VMESS_AEAD_FORCED=false \
-p $port:2053 \
-p $node_port1:$node_port1 \
-p $node_port2:$node_port2 \
-v "$PWD/db/:/etc/x-ui/" \
-v "$PWD/cert/:/root/cert/" \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
echo -e "${GREEN}3X-UI 安装完成。${RESET}"
echo "访问信息:"
echo "URL: http://$public_ip:$port"
echo "随机生成两个节点端口,后续自行添加。"
echo "节点端口: $node_port1"
echo "节点端口: $node_port2"
echo "节点端口: $node_port3"
;;
3)
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
echo -e "${GREEN}3X-UI 安装完成。${RESET}"
echo "访问信息:"
echo "输入 x-ui 进行修改设置"
echo "URL: http://$public_ip:2053"
;;
*) echo "无效的选项,请输入 0-3。" ;;
esac
echo "------------------"
echo "默认用户名: admin"
echo "默认密码: admin"
echo "------------------"
echo "请立即更改默认密码!"
echo "------------------"
echo "GIthub: https://github.com/MHSanaei/3x-ui"
echo "------------------"
read -p "按 回车键 返回 主菜单 ..."
}
# 更新 3X-UI
update_3x_ui() {
echo "正在更新 3X-UI 面板至最新版本..."
if docker ps -a | grep -q 3x-ui; then
docker stop 3x-ui > /dev/null 2>&1
docker rm 3x-ui > /dev/null 2>&1
install_3x_ui
echo "3X-UI 面板已更新至最新版本。"
else
echo "错误:未找到 3x-ui 容器。请先安装 3X-UI。"
return 1
fi
}
# 卸载 3X-UI
uninstall_3x_ui() {
read -p "您确定要卸载 3X-UI 面板吗?(y/n): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "卸载操作已取消。"
return
fi
if docker ps -a | grep -q 3x-ui; then
docker stop 3x-ui > /dev/null 2>&1
docker rm 3x-ui > /dev/null 2>&1
fi
if [ -d "$PWD/db" ]; then
rm -rf "$PWD/db"
fi
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'mhsanaei/3x-ui'); do
docker rmi "$image" > /dev/null 2>&1
done
echo -e "${GREEN}3X-UI 卸载完成。${RESET}"
}
############# o11 #############
# 安装 o11
install_o11() {
echo "正在安装 o11 面板..."
local port=$(generate_random_port)
if check_if_in_china; then
local public_ip="{路由IP}"
else
local public_ip=$(curl -s ifconfig.me || echo "{公网IP}")
fi
docker run -d --restart=always -p $port:1234 --name o11 wechatofficial/o11:latest
echo -e "${GREEN}o11 安装完成。${RESET}"
echo "访问信息:"
echo "URL: http://$public_ip:$port"
echo "小白教程: https://pixman.io/topics/118"
echo "请根据 o11 的文档进行配置和管理。"
read -p "按 回车键 返回 主菜单 ..."
}
# 卸载 o11
uninstall_o11() {
read -p "您确定要卸载 o11 面板吗?(y/n): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "卸载操作已取消。"
return
fi
if docker ps -a | grep -q o11; then
docker stop o11 > /dev/null 2>&1
docker rm o11 > /dev/null 2>&1
fi
for image in $(docker images --format '{{.Repository}}:{{.Tag}}' | grep 'wechatofficial/o11'); do
docker rmi "$image" > /dev/null 2>&1
done
echo -e "${GREEN}o11 卸载完成。${RESET}"
}
############# 1Panel #############
# 安装 1Panel
install_1panel() {
echo "正在安装 1Panel 面板..."
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
echo "GIthub: https://github.com/1Panel-dev/1Panel"
echo -e "${GREEN}1Panel 安装完成。${RESET}"
}
# 设置 1Panel
set_1panel() {
1pctl user-info
1pctl update password
}
# 卸载 1Panel
uninstall_1panel() {
read -p "您确定要卸载 1Panel 吗?(y/n): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "卸载操作已取消。"
return
fi
if command -v 1pctl > /dev/null 2>&1; then
1pctl uninstall
fi
echo -e "${GREEN}1Panel 卸载完成。${RESET}"
}
############# 辅助函数 #############
# 检查 网络 是否支持外网
check_internet_connection() {
if curl -s --max-time 8 google.com > /dev/null; then
return 0 # 能连接外网
else
return 1 # 不能连接外网
fi
}
# 检查 IP 归属地
check_if_in_china() {
local sources=(
"https://myip.ipip.net"
"https://ipinfo.io/country"
"http://ip-api.com/json/"
)
for source in "${sources[@]}"; do
response=$(curl -s "$source")
if echo "$response" | grep -qiE "中国|China|CN"; then
return 0
fi
done
return 1
}
# 检查 Docker 是否安装
check_docker() {
if ! command -v docker &> /dev/null; then
echo -e "${CYAN}Docker 未安装,正在进行安装...${RESET}"
install_docker
else
echo -e "${GREEN}Docker 已安装。${RESET}"
fi
}
# 选择 Docker 版本
install_docker() {
OS=$(lsb_release -is 2>/dev/null || cat /etc/os-release | grep '^ID=' | cut -d= -f2 | tr -d '"')
ARCH=$(uname -m)
case "$OS" in
Ubuntu)
echo "检测到系统为 Ubuntu,正在安装 Docker..."
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce
;;
Debian|Armbian)
echo "检测到系统为 Debian 或 Armbian,正在安装 Docker..."
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce
;;
centos|rhel|fedora)
echo "检测到系统为 CentOS,正在安装 Docker..."
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
;;
openwrt|lede)
echo "检测到系统为 OpenWRT/LEDE,正在安装 Docker..."
opkg update
opkg install dockerd docker-compose luci-app-dockerman
/etc/init.d/dockerd start
/etc/init.d/dockerd enable
;;
*)
echo "不支持的操作系统: $OS"
exit 1
;;
esac
# 如果不是 OpenWRT/LEDE,则启动和启用 Docker
if [[ "$OS" != "openwrt" && "$OS" != "lede" ]]; then
sudo systemctl start docker
sudo systemctl enable docker
fi
echo -e "${GREEN}Docker 安装完成。${RESET}"
}
# 检查jq 工具 是否安装
check_and_install_jq() {
if ! command -v jq &> /dev/null; then
if check_if_in_china; then
sudo apt-get update && sudo apt-get install -y jq --allow-releaseinfo-change
elif command -v apt-get &> /dev/null; then
sudo apt-get update && sudo apt-get install -y jq
elif command -v yum &> /dev/null; then
sudo yum install -y jq
elif command -v apk &> /dev/null; then
sudo apk add --no-cache jq
elif command -v opkg &> /dev/null; then # OpenWrt, Entware 环境
opkg update && opkg install jq
else
return 1 # jq 安装失败
fi
else
return 0 # jq 已安装
fi
}
# 清理 Docker 工具
cleanup_docker() {
echo -e "\n🚨 警告:此操作将删除所有已停止的容器、未使用的镜像和卷。"
read -p "你确认要继续吗?(y/n,默认n): " confirm
confirm=${confirm:-n}
if [[ "$confirm" != "y" ]]; then
echo -e "清理已取消。\n"
return
fi
docker system prune -a --volumes -f
echo -e "🎉 清理完成。"
read -p "按 回车键 返回 主菜单 ..."
}
# 转换 Cron 表达式
parse_cron_schedule() {
local schedule="$1"
local minute=$(echo "$schedule" | cut -d' ' -f1)
local hour=$(echo "$schedule" | cut -d' ' -f2)
local hour_list=()
local minute_desc=""
if [[ "$minute" == "0" ]]; then
minute_desc="整点"
else
minute_desc=" ${minute}"
fi
if [[ "$hour" == "*" ]]; then
hour_list+=("每小时")
elif [[ "$hour" == */* ]]; then
local interval=$(echo "$hour" | cut -d'/' -f2)
hour_list+=("${interval} 小时")
else
IFS=',' read -r -a hours <<< "$hour"
for h in "${hours[@]}"; do
if [[ "$h" =~ ^[0-9]+$ ]]; then
hour_list+=("每天 ${h}")
fi
done
fi
if [[ ${#hour_list[@]} -gt 0 ]]; then
echo "---------------------------------------------------------"
echo -e "${CYAN}■ 服务器将于${hour_list[*]}${minute_desc},进行检测更新。${RESET}"
echo "---------------------------------------------------------"
fi
}
# 生成随机端口
generate_random_port() {
local port
while :; do
port=$(shuf -i 20000-65535 -n 1)
ss -tuln | grep -q :$port || { echo "$port"; break; }
done
}
# 更新 SH 脚本
download_pixman() {
REMOTE_VERSION=$(curl -s "https://yang-1989.eu.org/pixman_version.txt")
if [ $? -ne 0 ]; then
echo -e "${RED}无法检测版本,请检查网络连接。${RESET}"
return
fi
if [ -f "$SCRIPT_PATH" ]; then
LOCAL_VERSION=$(grep -oP '(?<=^# 最新版本:).*' "$SCRIPT_PATH")
else
LOCAL_VERSION=""
fi
if [ "$REMOTE_VERSION" != "$LOCAL_VERSION" ]; then
echo "正在下载最新版本的 Pixman 脚本..."
curl -o "$SCRIPT_PATH" "https://yang-1989.eu.org/pixman.sh"
chmod +x "$SCRIPT_PATH"
echo -e "${GREEN}最新 $REMOTE_VERSION 版本下载已完成。${RESET}"
# echo "设置 'y' 为快捷启动命令..."
if [ ! -f ~/.bashrc ]; then
touch ~/.bashrc
fi
if ! grep -q "alias y=" ~/.bashrc; then
echo "alias y='bash \"$SCRIPT_PATH\" --from-y'" >> ~/.bashrc
source ~/.bashrc
fi
fi
}
# 脚本信息
script_log() {
echo "------------------------------------------------"
echo "Pixman 懒人脚本"
echo "项目地址: https://pixman.io/"
echo "脚本日志: https://pixman.io/topics/142"
echo "作者: YanG"
echo "当前版本号: $(grep -oP '(?<=^# 最新版本:).*' "$SCRIPT_PATH")"
echo "最后更新时间: 2024.10.24"
echo "更新内容: 优化 CN 判断,修复 Allinone 部署 BUG。计划 增加 Sub Store 部署,独立 watchtower 设置"
echo "------------------------------------------------"
read -p "按 回车键 返回 主菜单 ..."
}
############# 主程序逻辑 #############
load_parameters # 加载配置参数
download_pixman # 检查脚本更新
# 检查是否启动定时任务
if [ "$1" == "--auto" ]; then
echo "定时任务进行中..."
check_update
exit 0
fi
# 主循环
while true; do
show_menu
read -p "请选择操作: " choice
case "$choice" in
1) # 显示 pixman 菜单
while true; do
show_pixman_menu
read -p "请输入选项 (0-5): " pixman_choice
case "$pixman_choice" in
1)
check_docker
check_update
set_cron_job
live_pixman
;;
2)
set_parameters
set_cron_job
live_pixman
;;
3)
live_pixman
;;
4)
Convert_pixman
;;
5)
uninstall_pixman
;;
0)
echo "返回主菜单。"
break
;;
*)
echo "无效的选项,请输入 0-5。"
;;
esac
done
;;
2) # 显示 allinone 菜单
while true; do
show_allinone_menu
read -p "请输入选项 (0-4): " allinone_choice
case "$allinone_choice" in
1) check_docker ; install_allinone ;;
2) check_docker ; install_av3a ;;
3) proxy_allinone ;;
4) uninstall_allinone ;;
0) echo "返回主菜单。" ; break ;;
*) echo "无效的选项,请输入 0-4。" ;;
esac
done
;;
3) # 工具箱
while true; do
show_toolbox_menu
read -p "请输入选项 (0-4): " toolbox_choice
case "$toolbox_choice" in
1) # 1Panel 相关操作
while true; do
show_1panel_menu
read -p "请输入选项 (0-3): " panel_choice
case "$panel_choice" in
1) install_1panel ;;
2) uninstall_1panel ;;
3) set_1panel ;;
0) echo "返回上级菜单。" ; break ;;
*) echo "无效的选项,请输入 0-3。" ;;
esac
done
;;
2) # o11 相关操作
while true; do
show_o11_menu
read -p "请输入选项 (0-2): " o_choice
case "$o_choice" in
1) check_docker ; install_o11 ;;
2) uninstall_o11 ;;
0) echo "返回上级菜单。" ; break ;;
*) echo "无效的选项,请输入 0-2。" ;;
esac
done
;;
3) # 3X-UI 相关操作
while true; do
show_3x_ui_menu
read -p "请输入选项 (0-3): " ui_choice
case "$ui_choice" in
1) check_docker ; install_3x_ui ;;
2) update_3x_ui ;;
3) uninstall_3x_ui ;;
0) echo "返回上级菜单。" ; break ;;
*) echo "无效的选项,请输入 0-3。" ;;
esac
done
;;
4) cleanup_docker ;;
0) echo "返回主菜单。" ; break ;;
*) echo "无效的选项,请输入 0-3。" ;;
esac
done
;;
4) script_log ;;
0) echo "退出脚本。" ; exit 0 ;;
*) echo "无效的选项,请输入 0-4。" ;;
esac
done