From ee030a8e09cea3605dc6d32e82e00573fb5b1d38 Mon Sep 17 00:00:00 2001 From: fscarmen <62703343+fscarmen@users.noreply.github.com> Date: Mon, 7 Apr 2025 02:01:40 +0000 Subject: [PATCH] v1.2.16 Use OpenRC on Alpine to replace systemctl (Python3-compatible version). --- README.md | 9 +- docker_init.sh | 2 +- sing-box.sh | 656 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 475 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index 29136ef..6662269 100644 --- a/README.md +++ b/README.md @@ -19,18 +19,21 @@ * * * ## 1.更新信息 +2025.04.06 v1.2.16 Use OpenRC on Alpine to replace systemctl (Python3-compatible version); 在 Alpine 系统中使用 OpenRC 取代兼容 Python3 的 systemctl 实现 + 2025.04.05 v1.2.15 Supports output for clients such as Shadowrocket, Clash Mihomo, and Sing-box; 支持小火箭、Clash Mihomo、Sing-box 客户端输出 2025.03.23 v1.2.14 Added support for the AnyTLS protocol. Thanks to [Betterdoitnow] for providing the configuration; 新增对 AnyTLS 协议的支持,感谢 [Betterdoitnow] 提供的配置 -2025.03.18 v1.2.13 Compatible with Sing-box 1.12.0-alpha.18+; 适配 Sing-box 1.12.0-alpha.18+ - -2025.01.31 v1.2.12 In order to prevent sing-box from upgrading to a certain version which may cause errors, add a mandatory version file; 以防止sing-box某个版本升级导致运行报错,增加强制指定版本号文件
历史更新 history(点击即可展开或收起)
+>2025.03.18 v1.2.13 Compatible with Sing-box 1.12.0-alpha.18+; 适配 Sing-box 1.12.0-alpha.18+ +> +>2025.01.31 v1.2.12 In order to prevent sing-box from upgrading to a certain version which may cause errors, add a mandatory version file; 以防止sing-box某个版本升级导致运行报错,增加强制指定版本号文件 +> >2025.01.28 v1.2.11 1. Add server-side time synchronization configuration; 2. Replace some CDNs; 3. Fix the bug of getting the latest version error when upgrading; 1. 添加服务端时间同步配置; 2. 替换某些 CDN; 3. 修复升级时获取最新版本错误的 bu > >2024.12.31 v1.2.10 Adapted v1.11.0-beta.17 to add port hopping for hysteria2 in sing-box client output; 适配 v1.11.0-beta.17,在 sing-box 客户端输出中添加 hysteria2 的端口跳跃 diff --git a/docker_init.sh b/docker_init.sh index f153a3e..3335a2a 100644 --- a/docker_init.sh +++ b/docker_init.sh @@ -34,7 +34,7 @@ check_latest_sing-box() { # 获取最终版本号 local VERSION=$(wget --no-check-certificate --tries=2 --timeout=3 -qO- https://api.github.com/repos/SagerNet/sing-box/releases | awk -F '["v]' -v var="tag_name.*$FORCE_VERSION" '$0 ~ var {print $5; exit}') - VERSION=${VERSION:-'1.12.0-alpha.23'} + VERSION=${VERSION:-'1.12.0-beta.1'} echo "$VERSION" } diff --git a/sing-box.sh b/sing-box.sh index 79e95e7..3551550 100644 --- a/sing-box.sh +++ b/sing-box.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # 当前脚本版本号 -VERSION='v1.2.15 (2025.04.05)' +VERSION='v1.2.16 (2025.04.06)' # 各变量默认值 GH_PROXY='https://ghproxy.lvedong.eu.org/' @@ -27,8 +27,8 @@ mkdir -p $TEMP_DIR E[0]="Language:\n 1. English (default) \n 2. 简体中文" C[0]="${E[0]}" -E[1]="Added support for the AnyTLS protocol. Thanks to [Betterdoitnow] for providing the configuration. Supports output for clients such as Shadowrocket, Clash Mihomo, and Sing-box." -C[1]="新增对 AnyTLS 协议的支持,感谢 [Betterdoitnow] 提供的配置。支持小火箭、Clash Mihomo、Sing-box 客户端输出" +E[1]="1. Added support for the AnyTLS protocol. Thanks to [Betterdoitnow] for providing the configuration. Supports output for clients such as Shadowrocket, Clash Mihomo, and Sing-box; 2. Use OpenRC on Alpine to replace systemctl (Python3-compatible version). " +C[1]="1. 新增对 AnyTLS 协议的支持,感谢 [Betterdoitnow] 提供的配置。支持小火箭、Clash Mihomo、Sing-box 客户端输出; 2. 在 Alpine 系统中使用 OpenRC 取代兼容 Python3 的 systemctl 实现" E[2]="Downloading Sing-box. Please wait a seconds ..." C[2]="下载 Sing-box 中,请稍等 ..." E[3]="Input errors up to 5 times.The script is aborted." @@ -229,6 +229,16 @@ E[100]="Can't get the official latest version. Script exits." C[100]="获取不到官方的最新版本,脚本退出!" E[101]="The contents of the AnyTLS configuration file need to be updated for the sing_box kernel." C[101]="AnyTLS 配置文件内容,需要更新 sing_box 内核" +E[102]="Backing up old version sing-box to ${WORK_DIR}/sing-box.bak" +C[102]="已备份旧版本 sing-box 到 ${WORK_DIR}/sing-box.bak" +E[103]="New version \$ONLINE is running successfully, backup file deleted" +C[103]="新版本 \$ONLINE 运行成功,已删除备份文件" +E[104]="New version failed to run \$ONLINE, restoring old version \$LOCAL ..." +C[104]="新版本 \$ONLINE 运行失败,正在恢复旧版本 \$LOCAL ..." +E[105]="Successfully restored old version \$LOCAL" +C[105]="已成功恢复旧版本 \$LOCAL" +E[106]="Failed to restore old version \$LOCAL, please check manually" +C[106]="恢复旧版本 \$LOCAL 失败,请手动检查" # 自定义字体彩色,read 函数 warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色 @@ -434,7 +444,10 @@ change_argo() { error "\n $(text 61) " fi - case $(grep "ExecStart=" /etc/systemd/system/argo.service) in + # 根据系统类型检查 Argo 服务配置 + [ "$SYSTEM" = 'Alpine' ] && local ARGO_CONFIG=$(grep '^command_args=' /etc/init.d/argo) || local ARGO_CONFIG=$(grep "ExecStart=" /etc/systemd/system/argo.service) + + case "$ARGO_CONFIG" in *--config* ) ARGO_TYPE='Json' ;; @@ -443,36 +456,45 @@ change_argo() { ;; * ) ARGO_TYPE='Try' - cmd_systemctl enable argo && sleep 2 && [ "$(systemctl is-active argo)" = 'active' ] && fetch_quicktunnel_domain + cmd_systemctl enable argo && sleep 2 && cmd_systemctl status argo &>/dev/null && fetch_quicktunnel_domain esac fetch_nodes_value hint "\n $(text 90) \n" unset ARGO_DOMAIN hint " $(text 91) \n" && reading " $(text 24) " CHANGE_TO - case "$CHANGE_TO" in - 1 ) - cmd_systemctl disable argo - [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} - sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto --no-autoupdate --url http://localhost:$PORT_NGINX@g" /etc/systemd/system/argo.service - ;; - 2 ) - [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} - input_argo_auth is_change_argo - cmd_systemctl disable argo - if [ -n "$ARGO_TOKEN" ]; then - sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto run --token ${ARGO_TOKEN}@g" /etc/systemd/system/argo.service - elif [ -n "$ARGO_JSON" ]; then - sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto --config ${WORK_DIR}/tunnel.yml run@g" /etc/systemd/system/argo.service - fi - [ -s ${WORK_DIR}/conf/17_${NODE_TAG[6]}_inbounds.json ] && sed -i "s/VMESS_HOST_DOMAIN.*/VMESS_HOST_DOMAIN\": \"$ARGO_DOMAIN\"/" ${WORK_DIR}/conf/17_${NODE_TAG[6]}_inbounds.json - [ -s ${WORK_DIR}/conf/18_${NODE_TAG[7]}_inbounds.json ] && sed -i "s/\"server_name\":.*/\"server_name\": \"$ARGO_DOMAIN\",/" ${WORK_DIR}/conf/18_${NODE_TAG[7]}_inbounds.json - ;; - * ) - exit 0 - esac + case "$CHANGE_TO" in + 1 ) + cmd_systemctl disable argo + [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} + + # 根据系统类型修改配置文件 + [ "$SYSTEM" = 'Alpine' ] && sed -i "s@^command_args=.*@command_args=\"--edge-ip-version auto --no-autoupdate --url http://localhost:$PORT_NGINX\"@g" /etc/init.d/argo || sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto --no-autoupdate --url http://localhost:$PORT_NGINX@g" /etc/systemd/system/argo.service + ;; + 2 ) + [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} + input_argo_auth is_change_argo + cmd_systemctl disable argo + + if [ -n "$ARGO_TOKEN" ]; then + [ "$SYSTEM" = 'Alpine' ] && sed -i "s@^command_args=.*@command_args=\"--edge-ip-version auto run --token ${ARGO_TOKEN}\"@g" /etc/init.d/argo || sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto run --token ${ARGO_TOKEN}@g" /etc/systemd/system/argo.service + elif [ -n "$ARGO_JSON" ]; then + [ "$SYSTEM" = 'Alpine' ] && sed -i "s@^command_args=.*@command_args=\"--edge-ip-version auto --config ${WORK_DIR}/tunnel.yml run\"@g" /etc/init.d/argo || sed -i "s@ExecStart=.*@ExecStart=${WORK_DIR}/cloudflared tunnel --edge-ip-version auto --config ${WORK_DIR}/tunnel.yml run@g" /etc/systemd/system/argo.service + fi + + # 更新相关配置文件中的域名 + [ -s ${WORK_DIR}/conf/17_${NODE_TAG[6]}_inbounds.json ] && sed -i "s/VMESS_HOST_DOMAIN.*/VMESS_HOST_DOMAIN\": \"$ARGO_DOMAIN\"/" ${WORK_DIR}/conf/17_${NODE_TAG[6]}_inbounds.json + [ -s ${WORK_DIR}/conf/18_${NODE_TAG[7]}_inbounds.json ] && sed -i "s/\"server_name\":.*/\"server_name\": \"$ARGO_DOMAIN\",/" ${WORK_DIR}/conf/18_${NODE_TAG[7]}_inbounds.json + ;; + * ) + exit 0 + esac + + # 启用 Argo 服务 cmd_systemctl enable argo + + # 更新节点信息和配置 fetch_nodes_value export_nginx_conf_file export_list @@ -513,39 +535,69 @@ check_install() { [ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping fi - # 检测是否安装其他 sing-box systemd 状态,和是否其他一键脚本 - if [ -s /etc/systemd/system/sing-box.service ]; then - SYSTEMD_EXECSTART=$(grep '^ExecStart=' /etc/systemd/system/sing-box.service) - case "$SYSTEMD_EXECSTART" in - 'ExecStart=/etc/sing-box/sing-box run -C /etc/sing-box/conf/' ) - [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) || STATUS[0]=$(text 27) - ;; - 'ExecStart=/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json' ) - SING_BOX_SCRIPT='mack-a/v2ray-agent' && error "\n $(text 99) \n" - ;; - 'ExecStart=/etc/s-box/sing-box run -c /etc/s-box/sb.json' ) - SING_BOX_SCRIPT='yonggekkk/sing-box_hysteria2_tuic_argo_reality' && error "\n $(text 99) \n" - ;; - 'ExecStart=/usr/local/s-ui/bin/runSingbox.sh' ) - SING_BOX_SCRIPT='alireza0/s-ui' && error "\n $(text 99) \n" - ;; - 'ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json' ) - SING_BOX_SCRIPT='FranzKafkaYu/sing-box-yes' && error "\n $(text 99) \n" - ;; - * ) - SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" - esac - elif [ -s /lib/systemd/system/sing-box.service ]; then - SYSTEMD_EXECSTART=$(grep '^ExecStart=' /lib/systemd/system/sing-box.service) - case "$SYSTEMD_EXECSTART" in - 'ExecStart=/etc/sing-box/bin/sing-box run -c /etc/sing-box/config.json -C /etc/sing-box/conf' ) - SING_BOX_SCRIPT='233boy/sing-box' && error "\n $(text 99) \n" - ;; - * ) - SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" - esac + if [ "$SYSTEM" = 'Alpine' ]; then + # Alpine 系统使用 OpenRC 检查服务 + if [ -s /etc/init.d/sing-box ]; then + local OPENRC_EXECSTART=$(grep '^command=' /etc/init.d/sing-box) + case "$OPENRC_EXECSTART" in + *"${WORK_DIR}/sing-box"* ) + if rc-service sing-box status &>/dev/null; then + STATUS[0]=$(text 28) + else + STATUS[0]=$(text 27) + fi + ;; + * ) + SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" + esac + else + STATUS[0]=$(text 26) + fi else - STATUS[0]=$(text 26) + # 非 Alpine 系统使用 systemd 检查服务 + if [ -s /etc/systemd/system/sing-box.service ]; then + SYSTEMD_EXECSTART=$(grep '^ExecStart=' /etc/systemd/system/sing-box.service) + case "$SYSTEMD_EXECSTART" in + 'ExecStart=/etc/sing-box/sing-box run -C /etc/sing-box/conf/' | 'ExecStart=/etc/sing-box/sing-box run -C /etc/sing-box/conf' ) + [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) || STATUS[0]=$(text 27) + ;; + 'ExecStart=/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json' ) + SING_BOX_SCRIPT='mack-a/v2ray-agent' && error "\n $(text 99) \n" + ;; + 'ExecStart=/etc/s-box/sing-box run -c /etc/s-box/sb.json' ) + SING_BOX_SCRIPT='yonggekkk/sing-box_hysteria2_tuic_argo_reality' && error "\n $(text 99) \n" + ;; + 'ExecStart=/usr/local/s-ui/bin/runSingbox.sh' ) + SING_BOX_SCRIPT='alireza0/s-ui' && error "\n $(text 99) \n" + ;; + 'ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json' ) + SING_BOX_SCRIPT='FranzKafkaYu/sing-box-yes' && error "\n $(text 99) \n" + ;; + * ) + # 检查是否是自己的脚本安装的,但路径略有不同 + if [[ "$SYSTEMD_EXECSTART" =~ "ExecStart=/etc/sing-box/sing-box run" ]]; then + [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) || STATUS[0]=$(text 27) + else + SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" + fi + esac + elif [ -s /lib/systemd/system/sing-box.service ]; then + SYSTEMD_EXECSTART=$(grep '^ExecStart=' /lib/systemd/system/sing-box.service) + case "$SYSTEMD_EXECSTART" in + 'ExecStart=/etc/sing-box/bin/sing-box run -c /etc/sing-box/config.json -C /etc/sing-box/conf' ) + SING_BOX_SCRIPT='233boy/sing-box' && error "\n $(text 99) \n" + ;; + * ) + # 检查是否是自己的脚本安装的,但路径略有不同 + if [[ "$SYSTEMD_EXECSTART" =~ "ExecStart=/etc/sing-box/sing-box run" ]]; then + [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) || STATUS[0]=$(text 27) + else + SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" + fi + esac + else + STATUS[0]=$(text 26) + fi fi if [ "${STATUS[0]}" = "$(text 26)" ] && [ ! -s ${WORK_DIR}/sing-box ]; then @@ -567,81 +619,87 @@ check_install() { fi if [ "$NONINTERACTIVE_INSTALL" != 'noninteractive_install' ]; then - STATUS[1]=$(text 26) && IS_ARGO=no_argo && [ -s /etc/systemd/system/argo.service ] && IS_ARGO=is_argo && STATUS[1]=$(text 27) && [ "$(systemctl is-active argo)" = 'active' ] && STATUS[1]=$(text 28) + # 检查 Argo 服务状态 + STATUS[1]=$(text 26) && IS_ARGO=no_argo + [[ -s /etc/systemd/system/argo.service || -s /etc/init.d/argo ]] && IS_ARGO=is_argo && STATUS[1]=$(text 27) + cmd_systemctl status argo &>/dev/null && STATUS[1]=$(text 28) fi - if [ -s /etc/systemd/system/argo.service ]; then - local ARGO_CONTENT=$(grep '^ExecStart' /etc/systemd/system/argo.service) - if grep -q '\--token' <<< "$ARGO_CONTENT"; then - ARGO_TYPE=is_token_argo - elif grep -q '\--config' <<< "$ARGO_CONTENT"; then - ARGO_TYPE=is_json_argo - elif grep -q '\--url' <<< "$ARGO_CONTENT"; then - ARGO_TYPE=is_quicktunnel_argo + + # 检查 Argo 服务类型 + if [ "$SYSTEM" = 'Alpine' ]; then + if [ -s /etc/init.d/argo ]; then + local ARGO_CONTENT=$(grep '^command_args=' /etc/init.d/argo) + if grep -q '\--token' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_token_argo + elif grep -q '\--config' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_json_argo + elif grep -q '\--url' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_quicktunnel_argo + fi + fi + else + if [[ -s /etc/systemd/system/argo.service || -s /etc/init.d/argo ]]; then + local ARGO_CONTENT=$(grep '^ExecStart' /etc/systemd/system/argo.service) + if grep -q '\--token' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_token_argo + elif grep -q '\--config' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_json_argo + elif grep -q '\--url' <<< "$ARGO_CONTENT"; then + ARGO_TYPE=is_quicktunnel_argo + fi fi fi + + # 下载 cloudflared 如果需要 [[ "${STATUS[1]}" = "$(text 26)" || "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ]] && [ ! -s ${WORK_DIR}/cloudflared ] && { wget --no-check-certificate -qO $TEMP_DIR/cloudflared ${GH_PROXY}https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$ARGO_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/cloudflared >/dev/null 2>&1; }& } -# 检测 sing-box 的状态 -check_sing-box_status() { - case "${STATUS[0]}" in - "$(text 26)" ) - error "\n Sing-box $(text 28) $(text 38) \n" - ;; - "$(text 27)" ) - cmd_systemctl enable sing-box - [ "$(systemctl is-active sing-box)" = 'active' ] && info "\n Sing-box $(text 28) $(text 37) \n" || error "\n Sing-box $(text 28) $(text 38) \n" - ;; - "$(text 28)" ) - info "\n Sing-box $(text 28) $(text 37) \n" - esac -} - -# 检测 Argo 的状态 -check_argo_status() { - case "${STATUS[1]}" in - "$(text 26)" ) - error "\n Argo $(text 28) $(text 38) \n" - ;; - "$(text 27)" ) - cmd_systemctl enable argo - [ "$(systemctl is-active argo)" = 'active' ] && info "\n Argo $(text 28) $(text 37) \n" || error "\n Argo $(text 28) $(text 38) \n" - ;; - "$(text 28)" ) - info "\n Argo $(text 28) $(text 37) \n" - esac -} - # 为了适配 alpine,定义 cmd_systemctl 的函数 cmd_systemctl() { - local ENABLE_DISABLE=$1 - local APP=$2 - if [ "$ENABLE_DISABLE" = 'enable' ]; then - if [ "$SYSTEM" = 'Alpine' ]; then - systemctl start $APP - cat > /etc/local.d/$APP.start << EOF -#!/usr/bin/env bash - -systemctl start $APP -EOF - chmod +x /etc/local.d/$APP.start - rc-update add local >/dev/null 2>&1 - elif [ "$IS_CENTOS" = 'CentOS7' ]; then - systemctl enable --now $APP - [ "$APP" = 'sing-box' ] && [[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && $(type -p nginx) -c ${WORK_DIR}/nginx.conf + if [ "$SYSTEM" = 'Alpine' ]; then + case "$1" in + enable) + if [ "$2" = "sing-box" ]; then + rc-update add sing-box default >/dev/null 2>&1 + rc-service sing-box start >/dev/null 2>&1 + elif [ "$2" = "argo" ]; then + rc-update add argo default >/dev/null 2>&1 + rc-service argo start >/dev/null 2>&1 + fi + ;; + disable) + if [ "$2" = "sing-box" ]; then + rc-service sing-box stop >/dev/null 2>&1 + rc-update del sing-box default >/dev/null 2>&1 + elif [ "$2" = "argo" ]; then + rc-service argo stop >/dev/null 2>&1 + rc-update del argo default >/dev/null 2>&1 + fi + ;; + restart) + if [ "$2" = "sing-box" ]; then + rc-service sing-box restart >/dev/null 2>&1 + elif [ "$2" = "argo" ]; then + rc-service argo restart >/dev/null 2>&1 + fi + ;; + status) + if [ "$2" = "sing-box" ]; then + rc-service sing-box status + elif [ "$2" = "argo" ]; then + rc-service argo status + fi + ;; + esac + else + if [ "$1" = "enable" ] || [ "$1" = "disable" ]; then + systemctl "$1" --now "$2" >/dev/null 2>&1 + elif [ "$1" = "restart" ]; then + systemctl restart "$2" >/dev/null 2>&1 + elif [ "$1" = "status" ]; then + systemctl status "$2" else - systemctl enable --now $APP - fi - elif [ "$ENABLE_DISABLE" = 'disable' ]; then - if [ "$SYSTEM" = 'Alpine' ]; then - systemctl stop $APP - [ "$APP" = 'sing-box' ] && [[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && [ -s ${WORK_DIR}/nginx.conf ] && ss -nltp | grep $(awk '/listen/{print $2; exit}' ${WORK_DIR}/nginx.conf) | tr ',' '\n' | awk -F '=' '/pid/{print $2}' | sort -u | xargs kill -15 >/dev/null 2>&1 - rm -f /etc/local.d/$APP.start - elif [ "$IS_CENTOS" = 'CentOS7' ]; then - systemctl disable --now $APP - [ "$APP" = 'sing-box' ] && [[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && [ -s ${WORK_DIR}/nginx.conf ] && ss -nltp | grep $(awk '/listen/{print $2; exit}' ${WORK_DIR}/nginx.conf) | tr ',' '\n' | awk -F '=' '/pid/{print $2}' | sort -u | xargs kill -15 >/dev/null 2>&1 - else - systemctl disable --now $APP + systemctl "$@" >/dev/null 2>&1 fi fi } @@ -941,8 +999,8 @@ check_dependencies() { if [ "$SYSTEM" = 'Alpine' ]; then local CHECK_WGET=$(wget 2>&1 | head -n 1) grep -qi 'busybox' <<< "$CHECK_WGET" && ${PACKAGE_INSTALL[int]} wget >/dev/null 2>&1 - local DEPS_CHECK=("bash" "rc-update" "virt-what" "python3" "iptables" "ip6tables") - local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3" "iptables" "ip6tables") + local DEPS_CHECK=("bash" "rc-update" "virt-what" "iptables" "ip6tables") + local DEPS_INSTALL=("bash" "openrc" "virt-what" "iptables" "ip6tables") for g in "${!DEPS_CHECK[@]}"; do [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS_ALPINE+=(${DEPS_INSTALL[g]}) done @@ -952,13 +1010,12 @@ check_dependencies() { ${PACKAGE_INSTALL[int]} ${DEPS_ALPINE[@]} >/dev/null 2>&1 [[ -z "$VIRT" && "${DEPS_ALPINE[@]}" =~ 'virt-what' ]] && VIRT=$(virt-what | tr '\n' ' ') fi - - [ ! -x "$(type -p systemctl)" ] && wget --no-check-certificate --quiet ${GH_PROXY}https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py -O /bin/systemctl && chmod a+x /bin/systemctl fi # 检测 Linux 系统的依赖,升级库并重新安装依赖 - local DEPS_CHECK=("wget" "tar" "systemctl" "ss" "bash" "openssl") - local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl") + local DEPS_CHECK=("wget" "tar" "ss" "bash" "openssl") + local DEPS_INSTALL=("wget" "tar" "iproute2" "bash" "openssl") + [ "$SYSTEM" != 'Alpine' ] && DEPS_CHECK+=("systemctl") && DEPS_INSTALL+=("systemctl") for g in "${!DEPS_CHECK[@]}"; do [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS+=(${DEPS_INSTALL[g]}) done @@ -986,6 +1043,14 @@ check_dependencies() { else info "\n $(text 8) \n" fi + + # 对于 Alpine 系统,确保 OpenRC 服务已启动 + if [ "$SYSTEM" = 'Alpine' ]; then + if ! rc-service --list | grep -q "^openrc"; then + rc-update add openrc boot >/dev/null 2>&1 + rc-service openrc start >/dev/null 2>&1 + fi + fi } # 检查并安装 nginx @@ -994,8 +1059,9 @@ check_nginx() { info "\n $(text 7) nginx \n" ${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 - # 如果新安装的 Nginx ,先停掉服务 - systemctl disable --now nginx >/dev/null 2>&1 + + # 如果新安装的 Nginx,使用 cmd_systemctl 停止服务 + cmd_systemctl disable nginx fi } @@ -1806,7 +1872,64 @@ EOF # Sing-box 生成守护进程文件 sing-box_systemd() { - SING_BOX_SERVICE="[Unit] + if [ "$SYSTEM" = 'Alpine' ]; then + local OPENRC_SERVICE="#!/sbin/openrc-run + +name=\"sing-box\" +description=\"sing-box service\" +command=\"${WORK_DIR}/sing-box\" +command_args=\"run -C ${WORK_DIR}/conf\" +pidfile=\"/var/run/\${RC_SVCNAME}.pid\" +command_background=\"yes\" +output_log=\"${WORK_DIR}/logs/sing-box.log\" +error_log=\"${WORK_DIR}/logs/sing-box.log\" + +depend() { + need net + after net" + + # 如果配置了 Nginx,添加依赖 + [ -n "$PORT_NGINX" ] && OPENRC_SERVICE+=" + need nginx" + + # 添加 start_pre 函数,确保目录存在并设置正确权限 + OPENRC_SERVICE+=" +} + +start_pre() { + # 确保日志目录和PID目录存在并有正确权限 + mkdir -p ${WORK_DIR}/logs + mkdir -p /var/run + chmod 755 /var/run" + + # 如果配置了 Nginx,启动 Nginx + [ -n "$PORT_NGINX" ] && OPENRC_SERVICE+=" + $(type -p nginx) -c ${WORK_DIR}/nginx.conf" + + OPENRC_SERVICE+=" + # 确保 PID 文件不存在,避免启动失败 + rm -f \$pidfile +}" + + # 添加 stop_post 函数,用于在服务停止后清理 nginx 进程 + [ -n "$PORT_NGINX" ] && OPENRC_SERVICE+=" + +stop_post() { + # 查找并停止由 sing-box 启动的 nginx 进程 + # 使用 grep 查找包含特定配置文件的 nginx 进程 + local NGINX_PIDS=\$(ps -ef | grep \"[n]ginx -c ${WORK_DIR}/nginx.conf\" | awk '{print \$1}') + if [ -n \"\$NGINX_PIDS\" ]; then + for pid in \$NGINX_PIDS; do + kill \$pid 2>/dev/null + done + fi +}" + + echo "$OPENRC_SERVICE" > /etc/init.d/sing-box + chmod +x /etc/init.d/sing-box + else + # 原有的 systemd 服务创建代码 + SING_BOX_SERVICE="[Unit] Description=sing-box service Documentation=https://sing-box.sagernet.org After=network.target nss-lookup.target @@ -1818,9 +1941,9 @@ NoNewPrivileges=yes TimeoutStartSec=0 WorkingDirectory=${WORK_DIR} " - [[ -n "$PORT_NGINX" && "$IS_CENTOS" != 'CentOS7' ]] && SING_BOX_SERVICE+="ExecStartPre=$(type -p nginx) -c ${WORK_DIR}/nginx.conf + [[ -n "$PORT_NGINX" && "$IS_CENTOS" != 'CentOS7' ]] && SING_BOX_SERVICE+="ExecStartPre=$(type -p nginx) -c ${WORK_DIR}/nginx.conf " - SING_BOX_SERVICE+="ExecStart=${WORK_DIR}/sing-box run -C ${WORK_DIR}/conf/ + SING_BOX_SERVICE+="ExecStart=${WORK_DIR}/sing-box run -C ${WORK_DIR}/conf ExecReload=/bin/kill -HUP \$MAINPID Restart=on-failure RestartSec=10 @@ -1829,32 +1952,72 @@ LimitNOFILE=infinity [Install] WantedBy=multi-user.target" - echo "$SING_BOX_SERVICE" > /etc/systemd/system/sing-box.service + echo "$SING_BOX_SERVICE" > /etc/systemd/system/sing-box.service + systemctl daemon-reload + fi } # Argo 生成守护进程文件 argo_systemd() { - cat > /etc/systemd/system/argo.service << EOF + if [ "$SYSTEM" = 'Alpine' ]; then + # 分离命令和参数 + local COMMAND="${ARGO_RUNS%% --*}" # 提取命令部分(包括 cloudflared tunnel) + local ARGS="${ARGO_RUNS#$COMMAND}" # 提取参数部分 + + cat > /etc/init.d/argo << EOF +#!/sbin/openrc-run + +name="argo" +description="Cloudflare Tunnel service" +command="${COMMAND}" +command_args="${ARGS}" +pidfile="/var/run/\${RC_SVCNAME}.pid" +command_background="yes" +output_log="${WORK_DIR}/logs/argo.log" +error_log="${WORK_DIR}/logs/argo.log" + +depend() { + need net + after net +} + +start_pre() { + # 确保日志目录和PID目录存在并有正确权限 + mkdir -p ${WORK_DIR}/logs + mkdir -p /var/run + chmod 755 /var/run + + # 确保 PID 文件不存在,避免启动失败 + rm -f \$pidfile +} +EOF + chmod +x /etc/init.d/argo + else + # 原有的 systemd 服务创建代码 + cat > /etc/systemd/system/argo.service << EOF [Unit] Description=Cloudflare Tunnel After=network.target [Service] Type=simple +WorkingDirectory=$WORK_DIR NoNewPrivileges=yes TimeoutStartSec=0 -ExecStart=$ARGO_RUNS +ExecStart=${ARGO_RUNS} Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target EOF + systemctl daemon-reload + fi } # 获取原有各协议的参数,先清空所有的 key-value fetch_nodes_value() { - unset FILE NODE_NAME PORT_XTLS_REALITY UUID TLS_SERVER REALITY_PRIVATE REALITY_PUBLIC PORT_HYSTERIA2 OBFS PORT_TUIC TUIC_PASSWORD TUIC_CONGESTION_CONTROL PORT_SHADOWTLS SHADOWTLS_PASSWORD SHADOWSOCKS_METHOD PORT_SHADOWSOCKS PORT_TROJAN TROJAN_PASSWORD PORT_VMESS_WS VMESS_WS_PATH WS_SERVER_IP WS_SERVER_IP_SHOW VMESS_HOST_DOMAIN CDN PORT_VLESS_WS VLESS_WS_PATH VLESS_HOST_DOMAIN PORT_H2_REALITY PORT_GRPC_REALITY ARGO_DOMAIN PORT_ANYTLS + unset NODE_NAME PORT_XTLS_REALITY UUID TLS_SERVER REALITY_PRIVATE REALITY_PUBLIC PORT_HYSTERIA2 PORT_TUIC TUIC_PASSWORD TUIC_CONGESTION_CONTROL PORT_SHADOWTLS SHADOWTLS_PASSWORD SHADOWSOCKS_METHOD PORT_SHADOWSOCKS PORT_TROJAN TROJAN_PASSWORD PORT_VMESS_WS VMESS_WS_PATH WS_SERVER_IP WS_SERVER_IP_SHOW VMESS_HOST_DOMAIN CDN PORT_VLESS_WS VLESS_WS_PATH VLESS_HOST_DOMAIN PORT_H2_REALITY PORT_GRPC_REALITY ARGO_DOMAIN PORT_ANYTLS # 获取公共数据 ls ${WORK_DIR}/conf/*-ws*inbounds.json >/dev/null 2>&1 && SERVER_IP=$(awk -F '"' '/"WS_SERVER_IP_SHOW"/{print $4; exit}' ${WORK_DIR}/conf/*-ws*inbounds.json) || SERVER_IP=$(grep -A1 '"tag"' ${WORK_DIR}/list | sed -E '/-ws(-tls)*",$/{N;d}' | awk -F '"' '/"server"/{count++; if (count == 1) {print $4; exit}}') @@ -1863,7 +2026,15 @@ fetch_nodes_value() { [[ -z "$NODE_NAME_CONFIRM" && -s ${WORK_DIR}/subscribe/clash ]] && NODE_NAME_CONFIRM=$(awk -F "'" '/u: &u/{print $2; exit}' ${WORK_DIR}/subscribe/clash) # 如有 Argo,获取 Argo Tunnel - [[ ${STATUS[1]} =~ $(text 27)|$(text 28) ]] && grep -q '\--url' /etc/systemd/system/argo.service && cmd_systemctl enable argo && sleep 2 && [ "$(systemctl is-active argo)" = 'active' ] && fetch_quicktunnel_domain + if [[ ${STATUS[1]} =~ $(text 27)|$(text 28) ]]; then + if [ "$SYSTEM" = 'Alpine' ]; then + # Alpine 系统使用 OpenRC + grep -q '\--url' /etc/init.d/argo && { cmd_systemctl enable argo; sleep 2 && cmd_systemctl status argo &>/dev/null && fetch_quicktunnel_domain; } + else + # 非 Alpine 系统使用 systemd + grep -q '\--url' /etc/systemd/system/argo.service && { cmd_systemctl enable argo; sleep 2 && cmd_systemctl status argo &>/dev/null && fetch_quicktunnel_domain; } + fi + fi # 获取 Nginx 端口和路径 [[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && local NGINX_JSON=$(cat ${WORK_DIR}/nginx.conf) && @@ -1909,8 +2080,8 @@ fetch_quicktunnel_domain() { unset CLOUDFLARED_PID METRICS_ADDRESS ARGO_DOMAIN local QUICKTUNNEL_ERROR_TIME=20 until [ -n "$ARGO_DOMAIN" ]; do - [ "$SYSTEM" = 'Alpine' ] && CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="${WORK_DIR}" '$0 ~ WORK_DIR"/cloudflared" {print $1; exit}') || CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="${WORK_DIR}" '$0 ~ WORK_DIR"/cloudflared" {print $2; exit}') - [[ -z "$METRICS_ADDRESS" && "$CLOUDFLARED_PID" =~ ^[0-9]+$ ]] && METRICS_ADDRESS=$(ss -nltp | grep "pid=$CLOUDFLARED_PID" | awk '{print $4}') + [ "$SYSTEM" = 'Alpine' ] && local CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="${WORK_DIR}" '$0 ~ WORK_DIR"/cloudflared" {print $1; exit}') || local CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="${WORK_DIR}" '$0 ~ WORK_DIR"/cloudflared" {print $2; exit}') + [[ -z "$METRICS_ADDRESS" && "$CLOUDFLARED_PID" =~ ^[0-9]+$ ]] && local METRICS_ADDRESS=$(ss -nltp | grep "pid=$CLOUDFLARED_PID" | awk '{print $4}') [ -n "$METRICS_ADDRESS" ] && ARGO_DOMAIN=$(wget -qO- http://$METRICS_ADDRESS/quicktunnel | awk -F '"' '{print $4}') [[ ! "$ARGO_DOMAIN" =~ trycloudflare\.com$ ]] && (( QUICKTUNNEL_ERROR_TIME-- )) && sleep 2 || break [ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) " @@ -1948,23 +2119,40 @@ install_sing-box() { # 生成 Nginx 配置文件 [ -n "$PORT_NGINX" ] && export_nginx_conf_file - # 如果 Alpine 系统,放到开机自启动 - if [ "$SYSTEM" = 'Alpine' ]; then - cat > /etc/local.d/sing-box.start << EOF -#!/usr/bin/env bash + # 非 Alpine 系统启动 sing-box 服务 + [ "$SYSTEM" != 'Alpine' ] && cmd_systemctl daemon-reload + cmd_systemctl enable sing-box -systemctl start sing-box -EOF - chmod +x /etc/local.d/sing-box.start - rc-update add local >/dev/null 2>&1 + # 等待服务启动 + sleep 2 + + # 检查服务是否成功启动 + if cmd_systemctl status sing-box &>/dev/null; then + STATUS[0]=$(text 28) + info "\n Sing-box $(text 28) $(text 37) \n" + else + STATUS[0]=$(text 27) + error "\n Sing-box $(text 27) $(text 38) \n" + # 如果启动失败,再尝试重启 + cmd_systemctl restart sing-box fi - # 等待所有后台进程完成后,再次检测状态,运行 Sing-box - check_install - sleep 1 - check_sing-box_status + # 如果配置了 Argo,也启动 Argo 服务 if [ "$IS_ARGO" = 'is_argo' ]; then - [ "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ] && cmd_systemctl enable argo || check_argo_status + cmd_systemctl enable argo + + sleep 2 + + # 检查 Argo 服务是否成功启动 + if cmd_systemctl status argo &>/dev/null; then + STATUS[1]=$(text 28) + info "\n Argo $(text 28) $(text 37) \n" + else + STATUS[1]=$(text 27) + error "\n Argo $(text 27) $(text 38) \n" + # 如果启动失败,再尝试重启 + cmd_systemctl restart argo + fi fi } @@ -1973,15 +2161,6 @@ export_list() { check_install - #### v1.1.9 处理的 jq 和 qrencode 二进制文件代替系统依赖的问题,此处预计6月30日删除 - if [[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]]; then - [[ ! -s ${WORK_DIR}/jq && -s /usr/bin/jq ]] && cp /usr/bin/jq ${WORK_DIR}/ - if [ ! -s ${WORK_DIR}/qrencode ]; then - check_arch - wget -qO ${WORK_DIR}/qrencode ${GH_PROXY}https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH && chmod +x ${WORK_DIR}/qrencode - fi - fi - [ "$IS_INSTALL" != 'install' ] && fetch_nodes_value # IPv6 时的 IP 处理 @@ -2829,7 +3008,7 @@ change_protocols() { fi # 获取 ws 的 argo 或者 origin 状态 - if [ -s /etc/systemd/system/argo.service ]; then + if [[ -s /etc/systemd/system/argo.service || -s /etc/init.d/argo ]]; then local ARGO_ORIGIN_RULES_STATUS=is_argo ARGO_RUNS=$(sed -n "s/^ExecStart=\(.*\)/\1/gp" /etc/systemd/system/argo.service) elif ls ${WORK_DIR}/conf/*-ws*inbounds.json >/dev/null 2>&1; then @@ -2953,7 +3132,7 @@ change_protocols() { argo_systemd cmd_systemctl enable argo >/dev/null 2>&1 fi - elif [ -s /etc/systemd/system/argo.service ]; then + elif [[ -s /etc/systemd/system/argo.service || -s /etc/init.d/argo ]]; then cmd_systemctl disable argo >/dev/null 2>&1 rm -f /etc/systemd/system/argo.service [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.* @@ -2965,22 +3144,36 @@ change_protocols() { # 运行 sing-box cmd_systemctl enable sing-box + # 等待服务启动 + sleep 3 + # 再次检测状态,运行 sing-box check_install + case "${STATUS[0]}" in + "$(text 26)" ) + error "\n Sing-box $(text 28) $(text 38) \n" + ;; + "$(text 27)" ) + cmd_systemctl enable sing-box + cmd_systemctl status sing-box &>/dev/null && info "\n Sing-box $(text 28) $(text 37) \n" || error "\n Sing-box $(text 28) $(text 38) \n" + ;; + "$(text 28)" ) + info "\n Sing-box $(text 28) $(text 37) \n" + esac - check_sing-box_status - + # 导出节点和订阅服务信息 export_list } # 卸载 sing-box 全家桶 uninstall() { if [ -d ${WORK_DIR} ]; then - [ -s /etc/systemd/system/argo.service ] && ( cmd_systemctl disable argo 2>/dev/null; rm -f /etc/systemd/system/argo.service ) + [[ -s /etc/systemd/system/argo.service || -s /etc/init.d/argo ]] && ( cmd_systemctl disable argo &>/dev/null; rm -f /etc/systemd/system/argo.service ) if [ "$SYSTEM" = 'Alpine' ]; then - cmd_systemctl disable sing-box 2>/dev/null + [ -s /etc/init.d/sing-box ] && ( rc-service sing-box stop &>/dev/null; rc-update del sing-box default &>/dev/null; rm -f /etc/init.d/sing-box ) + [ -s /etc/init.d/argo ] && ( rc-service argo stop &>/dev/null; rc-update del argo default &>/dev/null; rm -f /etc/init.d/argo ) else - cmd_systemctl disable sing-box 2>/dev/null + cmd_systemctl disable sing-box &>/dev/null fi sleep 1 [[ -s ${WORK_DIR}/nginx.conf && $(ps -ef | grep 'nginx' | wc -l) -le 1 ]] && reading "\n $(text 83) " REMOVE_NGINX @@ -2991,13 +3184,6 @@ uninstall() { else error "\n $(text 15) \n" fi - - # 如果 Alpine 系统,删除开机自启动和python3版systemd - if [ "$SYSTEM" = 'Alpine' ]; then - rm -f /etc/local.d/{sing-box,argo}.start - rc-update add local >/dev/null 2>&1 - ! ls /etc/systemd/system/*.service >/dev/null 2>&1 && rm -f /bin/systemctl - fi } # Sing-box 的最新版本 @@ -3022,8 +3208,34 @@ version() { if [ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ]; then cmd_systemctl disable sing-box + + # 备份旧版本 + cp ${WORK_DIR}/sing-box ${WORK_DIR}/sing-box.bak + hint "\n $(text 102) \n" + + # 安装新版本 chmod +x $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box && mv $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ${WORK_DIR}/sing-box - cmd_systemctl enable sing-box && sleep 2 && [ "$(systemctl is-active sing-box)" = 'active' ] && info "\n Sing-box $(text 28) $(text 37) \n" || error "\n Sing-box $(text 28) $(text 38) \n" + cmd_systemctl enable sing-box + sleep 2 + + # 检查新版本是否成功运行 + if cmd_systemctl status sing-box &>/dev/null; then + # 新版本运行成功,删除备份 + rm -f ${WORK_DIR}/sing-box.bak + info "\n $(text 103) \n" + else + # 新版本运行失败,恢复旧版本 + warning "\n $(text 104) \n" + mv ${WORK_DIR}/sing-box.bak ${WORK_DIR}/sing-box + cmd_systemctl enable sing-box + sleep 2 + + if cmd_systemctl status sing-box &>/dev/null; then + info "\n $(text 105) \n" + else + error "\n $(text 106) \n" + fi + fi else error "\n $(text 42) " fi @@ -3072,8 +3284,60 @@ menu_setting() { OPTION[12]="12. $(text 76)" ACTION[1]() { export_list; exit 0; } - [ "${STATUS[0]}" = "$(text 28)" ] && ACTION[2]() { cmd_systemctl disable sing-box; [[ "$(systemctl is-active sing-box)" =~ 'inactive'|'unknown' ]] && info " Sing-box $(text 27) $(text 37)" || error " Sing-box $(text 27) $(text 38) "; } || ACTION[2]() { cmd_systemctl enable sing-box && [ "$(systemctl is-active sing-box)" = 'active' ] && info " Sing-box $(text 28) $(text 37)" || error " Sing-box $(text 28) $(text 38) "; } - [ "${STATUS[1]}" = "$(text 28)" ] && ACTION[3]() { cmd_systemctl disable argo; [[ "$(systemctl is-active argo)" =~ 'inactive'|'unknown' ]] && info " Argo $(text 27) $(text 37)" || error " Argo $(text 27) $(text 38) "; } || ACTION[3]() { cmd_systemctl enable argo && sleep 2 && [ "$(systemctl is-active argo)" = 'active' ] && info " Argo $(text 28) $(text 37)" && ( grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list ) || error " Argo $(text 28) $(text 38) "; } + + if [ "$SYSTEM" = 'Alpine' ]; then + # Alpine 系统使用 OpenRC 命令检查服务状态 + [ "${STATUS[0]}" = "$(text 28)" ] && ACTION[2]() { + cmd_systemctl disable sing-box + cmd_systemctl status sing-box &>/dev/null || info " Sing-box $(text 27) $(text 37)" || error " Sing-box $(text 27) $(text 38) " + } || ACTION[2]() { + cmd_systemctl enable sing-box + sleep 2 + cmd_systemctl status sing-box &>/dev/null && info " Sing-box $(text 28) $(text 37)" || error " Sing-box $(text 28) $(text 38) " + } + + [ "${STATUS[1]}" = "$(text 28)" ] && ACTION[3]() { + cmd_systemctl disable argo + cmd_systemctl status argo &>/dev/null || info " Argo $(text 27) $(text 37)" || error " Argo $(text 27) $(text 38) " + } || ACTION[3]() { + cmd_systemctl enable argo + sleep 2 + if cmd_systemctl status argo &>/dev/null; then + info " Argo $(text 28) $(text 37)" + # 根据系统类型检查不同的配置文件 + if [ "$SYSTEM" = 'Alpine' ]; then + grep -q '\--url' /etc/init.d/argo && fetch_quicktunnel_domain && export_list + else + grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list + fi + else + error " Argo $(text 28) $(text 38) " + fi + } + else + # 非 Alpine 系统使用 systemd 命令 + [ "${STATUS[0]}" = "$(text 28)" ] && ACTION[2]() { + cmd_systemctl disable sing-box + [[ "$(systemctl is-active sing-box)" =~ 'inactive'|'unknown' ]] && info " Sing-box $(text 27) $(text 37)" || error " Sing-box $(text 27) $(text 38) " + } || ACTION[2]() { + cmd_systemctl enable sing-box + [ "$(systemctl is-active sing-box)" = 'active' ] && info " Sing-box $(text 28) $(text 37)" || error " Sing-box $(text 28) $(text 38) " + } + + [ "${STATUS[1]}" = "$(text 28)" ] && ACTION[3]() { + cmd_systemctl disable argo + [[ "$(systemctl is-active argo)" =~ 'inactive'|'unknown' ]] && info " Argo $(text 27) $(text 37)" || error " Argo $(text 27) $(text 38) " + } || ACTION[3]() { + cmd_systemctl enable argo + sleep 2 + if [ "$(systemctl is-active argo)" = 'active' ]; then + info " Argo $(text 28) $(text 37)" + grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list + else + error " Argo $(text 28) $(text 38) " + fi + } + fi ACTION[4]() { change_argo; exit; } ACTION[5]() { change_start_port; exit; } ACTION[6]() { version; exit; } @@ -3161,14 +3425,19 @@ for z in ${!ALL_PARAMETER[@]}; do ;; -S ) check_install - if [ "${STATUS[0]}" = "$(text 26)" ];then + if [ "${STATUS[0]}" = "$(text 26)" ]; then error "\n Sing-box $(text 26) " elif [ "${STATUS[0]}" = "$(text 28)" ]; then cmd_systemctl disable sing-box - [[ "$(systemctl is-active sing-box)" =~ 'inactive'|'unknown' ]] && info "\n Sing-box $(text 27) $(text 37)" + cmd_systemctl status sing-box &>/dev/null || info "\n Sing-box $(text 27) $(text 37)" elif [ "${STATUS[0]}" = "$(text 27)" ]; then cmd_systemctl enable sing-box - [ "$(systemctl is-active sing-box)" = 'active' ] && info "\n Sing-box $(text 28) $(text 37)" + sleep 2 + if cmd_systemctl status sing-box &>/dev/null; then + info "\n Sing-box $(text 28) $(text 37)" + else + error "\n Sing-box $(text 28) $(text 38) " + fi fi exit 0 ;; @@ -3178,13 +3447,24 @@ for z in ${!ALL_PARAMETER[@]}; do error "\n Argo $(text 26) " elif [ "${STATUS[1]}" = "$(text 28)" ]; then cmd_systemctl disable argo - [[ "$(systemctl is-active argo)" =~ 'inactive'|'unknown' ]] && info "\n Argo $(text 27) $(text 37)" + if [ "$SYSTEM" = 'Alpine' ]; then + rc-service argo status &>/dev/null || info "\n Argo $(text 27) $(text 37)" + else + [[ "$(systemctl is-active argo)" =~ 'inactive'|'unknown' ]] && info "\n Argo $(text 27) $(text 37)" + fi elif [ "${STATUS[1]}" = "$(text 27)" ]; then cmd_systemctl enable argo sleep 2 - if [ "$(systemctl is-active argo)" = 'active' ]; then - info "\n Argo $(text 28) $(text 37)" - grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list + if [ "$SYSTEM" = 'Alpine' ]; then + if rc-service argo status &>/dev/null; then + info "\n Argo $(text 28) $(text 37)" + grep -q '\--url' /etc/init.d/argo && fetch_quicktunnel_domain && export_list + fi + else + if [ "$(systemctl is-active argo)" = 'active' ]; then + info "\n Argo $(text 28) $(text 37)" + grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list + fi fi fi exit 0