mirror of
https://github.com/fscarmen/sing-box.git
synced 2026-08-10 17:55:16 +08:00
v1.3.18 feat: add subscription toggle in sb -d menu
v1.3.18 feat: `sb -d` 菜单新增订阅开关功能
This commit is contained in:
@@ -24,18 +24,20 @@
|
|||||||
|
|
||||||
* * *
|
* * *
|
||||||
## 1.更新信息
|
## 1.更新信息
|
||||||
|
2026.07.25 v1.3.18 Add enable/disable subscriptions option in sb -d menu 2. Change v2rayN Hysteria2 Realm config from Finalmask field to ProtoExtraObj; sb -d 菜单新增 「订阅开关」,可随时开启关闭订阅
|
||||||
|
|
||||||
2026.07.20 v1.3.17 1. Add SIGHUP hot-reload support, replace restart sequences with reload; 2. Force base-config regeneration on upgrade to guarantee sing-box check passes; 1. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 2. 升级时强制重置基础配置至新版格式,保证兼容性
|
2026.07.20 v1.3.17 1. Add SIGHUP hot-reload support, replace restart sequences with reload; 2. Force base-config regeneration on upgrade to guarantee sing-box check passes; 1. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 2. 升级时强制重置基础配置至新版格式,保证兼容性
|
||||||
|
|
||||||
2026.07.16 v1.3.16 1. Add bind_interface option in sb -d menu to bind outbound traffic to a specific NIC; 2. Change v2rayN Hysteria2 Realm config from Finalmask field to ProtoExtraObj; 1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj
|
2026.07.16 v1.3.16 1. Add bind_interface option in sb -d menu to bind outbound traffic to a specific NIC; 2. Change v2rayN Hysteria2 Realm config from Finalmask field to ProtoExtraObj; 1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj
|
||||||
|
|
||||||
2026.07.01 v1.3.15 Add v2rayN Finalmask field for hysteria2 realm subscription output; v2rayN 订阅输出增加 Hysteria2 Realm 的 Finalmask 字段
|
|
||||||
|
|
||||||
2026.05.29 v1.3.14 Added optional custom warp route rule management, available after installation via [sb -d] without affecting the main installation flow; 增加可选的自定义 warp 路由规则管理,不影响主程序安装流程,安装后可通过 [sb -d] 按需管理
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>历史更新 history(点击即可展开或收起)</summary>
|
<summary>历史更新 history(点击即可展开或收起)</summary>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
>2026.07.01 v1.3.15 Add v2rayN Finalmask field for hysteria2 realm subscription output; v2rayN 订阅输出增加 Hysteria2 Realm 的 Finalmask 字段
|
||||||
|
>
|
||||||
|
>2026.05.29 v1.3.14 Added optional custom warp route rule management, available after installation via [sb -d] without affecting the main installation flow; 增加可选的自定义 warp 路由规则管理,不影响主程序安装流程,安装后可通过 [sb -d] 按需管理
|
||||||
|
>
|
||||||
>2026.05.18 v1.3.13 Added top-level http_clients configuration; 增加顶层的 http_clients 配置
|
>2026.05.18 v1.3.13 Added top-level http_clients configuration; 增加顶层的 http_clients 配置
|
||||||
>
|
>
|
||||||
>2026.05.14 v1.3.12 1. Add Hysteria2 Realm support for machines without public inbound access, with optional WARP-assisted hole punching for strict NAT environments; 2. Realm configuration export is supported for Clash/Mihomo and sing-box clients; 3. Hysteria2 Realm can be enabled or disabled directly via sb -d; 4. Non-interactive installs support --HY2_REALM and --HY2_WARP parameters; 1. 增加 Hysteria2 Realm 支持,适用于没有公网入口的机器,并可选 WARP 辅助打洞; 2. Realm 已支持导出 Clash/Mihomo 和 sing-box 客户端配置; 3. 修改节点配置时可直接开启或关闭 Hysteria2 Realm; 4. 无交互安装支持 --HY2_REALM 与 --HY2_WARP 参数
|
>2026.05.14 v1.3.12 1. Add Hysteria2 Realm support for machines without public inbound access, with optional WARP-assisted hole punching for strict NAT environments; 2. Realm configuration export is supported for Clash/Mihomo and sing-box clients; 3. Hysteria2 Realm can be enabled or disabled directly via sb -d; 4. Non-interactive installs support --HY2_REALM and --HY2_WARP parameters; 1. 增加 Hysteria2 Realm 支持,适用于没有公网入口的机器,并可选 WARP 辅助打洞; 2. Realm 已支持导出 Clash/Mihomo 和 sing-box 客户端配置; 3. 修改节点配置时可直接开启或关闭 Hysteria2 Realm; 4. 无交互安装支持 --HY2_REALM 与 --HY2_WARP 参数
|
||||||
|
|||||||
+103
-33
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# 当前脚本版本号
|
# 当前脚本版本号
|
||||||
VERSION='v1.3.17 (2026.07.20)'
|
VERSION='v1.3.18 (2026.07.25)'
|
||||||
|
|
||||||
# Github 反代加速代理
|
# Github 反代加速代理
|
||||||
GITHUB_PROXY=('https://hub.glowp.xyz/' 'https://proxy.vvvv.ee/')
|
GITHUB_PROXY=('https://hub.glowp.xyz/' 'https://proxy.vvvv.ee/')
|
||||||
@@ -40,8 +40,8 @@ mkdir -p "$TEMP_DIR"
|
|||||||
|
|
||||||
E[0]="Language:\n 1. English (default) \n 2. 简体中文"
|
E[0]="Language:\n 1. English (default) \n 2. 简体中文"
|
||||||
C[0]="${E[0]}"
|
C[0]="${E[0]}"
|
||||||
E[1]="1. Add bind_interface option in sb -d menu to bind outbound traffic to a specific NIC; 2. Change v2rayN Hysteria2 Realm config from Finalmask field to ProtoExtraObj; 3. add SIGHUP hot-reload support, replace restart sequences with reload; 4. force base-config regeneration on upgrade to guarantee sing-box check passes"
|
E[1]="1. Add bind_interface option in sb -d menu to bind outbound traffic to a specific NIC; 2. Add enable/disable subscriptions option in sb -d menu 2. Change v2rayN Hysteria2 Realm config from Finalmask field to ProtoExtraObj; 3. add SIGHUP hot-reload support, replace restart sequences with reload; 4. force base-config regeneration on upgrade to guarantee sing-box check passes"
|
||||||
C[1]="1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj; 3. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 4. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 4. 升级时强制重置基础配置至新版格式,保证兼容性"
|
C[1]="1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. sb -d 菜单新增 「订阅开关」,可随时开启关闭订阅; 3. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj; 4. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 4. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 5. 升级时强制重置基础配置至新版格式,保证兼容性"
|
||||||
E[2]="Downloading Sing-box. Please wait a seconds ..."
|
E[2]="Downloading Sing-box. Please wait a seconds ..."
|
||||||
C[2]="下载 Sing-box 中,请稍等 ..."
|
C[2]="下载 Sing-box 中,请稍等 ..."
|
||||||
E[3]="Input errors up to 5 times.The script is aborted."
|
E[3]="Input errors up to 5 times.The script is aborted."
|
||||||
@@ -142,8 +142,8 @@ E[50]="Please enter the \$TYPE domain name:"
|
|||||||
C[50]="请输入 \$TYPE 域名:"
|
C[50]="请输入 \$TYPE 域名:"
|
||||||
E[51]="Please choose or custom a cdn, http support is required:"
|
E[51]="Please choose or custom a cdn, http support is required:"
|
||||||
C[51]="请选择或输入 cdn,要求支持 http:"
|
C[51]="请选择或输入 cdn,要求支持 http:"
|
||||||
E[52]="Please set the ip \[\${WS_SERVER_IP_SHOW}] to domain \[\${TYPE_HOST_DOMAIN}], and set the origin rule to \[\${TYPE_PORT_WS}] in Cloudflare."
|
E[52]="Please set the ip [\${WS_SERVER_IP_SHOW}] to domain [\${TYPE_HOST_DOMAIN}], and set the origin rule to [\${TYPE_PORT_WS}] in Cloudflare."
|
||||||
C[52]="请在 Cloudflare 绑定 \[\${WS_SERVER_IP_SHOW}] 的域名为 \[\${TYPE_HOST_DOMAIN}], 并设置 origin rule 为 \[\${TYPE_PORT_WS}]"
|
C[52]="请在 Cloudflare 绑定 [\${WS_SERVER_IP_SHOW}] 的域名为 [\${TYPE_HOST_DOMAIN}], 并设置 origin rule 为 [\${TYPE_PORT_WS}]"
|
||||||
E[53]="Please select or enter the preferred address (domain / IPv4 / [IPv6], optional :port), the default is \${CDN_DOMAIN[0]}:"
|
E[53]="Please select or enter the preferred address (domain / IPv4 / [IPv6], optional :port), the default is \${CDN_DOMAIN[0]}:"
|
||||||
C[53]="请选择或者填入优选地址(域名 / IPv4 / [IPv6],可选 :端口),默认为 \${CDN_DOMAIN[0]}:"
|
C[53]="请选择或者填入优选地址(域名 / IPv4 / [IPv6],可选 :端口),默认为 \${CDN_DOMAIN[0]}:"
|
||||||
E[54]="Configuration check failed, new version \$ONLINE is incompatible with current config."
|
E[54]="Configuration check failed, new version \$ONLINE is incompatible with current config."
|
||||||
@@ -226,8 +226,8 @@ E[92]="Change the Argo tunnel (sb -t)"
|
|||||||
C[92]="更换 Argo 隧道 (sb -t)"
|
C[92]="更换 Argo 隧道 (sb -t)"
|
||||||
E[93]="Can't get the temporary tunnel domain, script exits. Feedback:[https://github.com/fscarmen/sing-box/issues]"
|
E[93]="Can't get the temporary tunnel domain, script exits. Feedback:[https://github.com/fscarmen/sing-box/issues]"
|
||||||
C[93]="获取不到临时隧道的域名,脚本退出,问题反馈:[https://github.com/fscarmen/sing-box/issues]"
|
C[93]="获取不到临时隧道的域名,脚本退出,问题反馈:[https://github.com/fscarmen/sing-box/issues]"
|
||||||
E[94]="Please bind \[\${ARGO_DOMAIN}] tunnel TYPE to HTTP and URL to \[\localhost:\${PORT_NGINX}] in Cloudflare."
|
E[94]="Please bind [\${ARGO_DOMAIN}] tunnel TYPE to HTTP and URL to [localhost:\${PORT_NGINX}] in Cloudflare."
|
||||||
C[94]="请在 Cloudflare 绑定 \[\${ARGO_DOMAIN}] 隧道 TYPE 为 HTTP,URL 为 \[\localhost:\${PORT_NGINX}]"
|
C[94]="请在 Cloudflare 绑定 [\${ARGO_DOMAIN}] 隧道 TYPE 为 HTTP,URL 为 [localhost:\${PORT_NGINX}]"
|
||||||
E[95]="netfilter-persistent installation failed, but the installation progress will not stop. portHopping forwarding rules are temporary rules, reboot may be invalidated."
|
E[95]="netfilter-persistent installation failed, but the installation progress will not stop. portHopping forwarding rules are temporary rules, reboot may be invalidated."
|
||||||
C[95]="netfilter-persistent安装失败,但安装进度不会停止。PortHopping转发规则为临时规则,重启可能失效"
|
C[95]="netfilter-persistent安装失败,但安装进度不会停止。PortHopping转发规则为临时规则,重启可能失效"
|
||||||
E[96]="netfilter-persistent is not started, PortHopping forwarding rules cannot be persisted. Reboot the system, the rules will be invalidated, please manually execute [netfilter-persistent save], continue the script does not affect the subsequent configuration."
|
E[96]="netfilter-persistent is not started, PortHopping forwarding rules cannot be persisted. Reboot the system, the rules will be invalidated, please manually execute [netfilter-persistent save], continue the script does not affect the subsequent configuration."
|
||||||
@@ -388,6 +388,10 @@ E[174]="Failed to update configuration. Please check manually. Suggestion: reins
|
|||||||
C[174]="更新配置后仍然无法检查成功,建议重装脚本"
|
C[174]="更新配置后仍然无法检查成功,建议重装脚本"
|
||||||
E[175]="Update base configuration? (Node configs will remain unaffected; only log, outbounds, endpoints, route, experimental, dns, ntp, http_clients, etc., will be reset) [Y/n]:"
|
E[175]="Update base configuration? (Node configs will remain unaffected; only log, outbounds, endpoints, route, experimental, dns, ntp, http_clients, etc., will be reset) [Y/n]:"
|
||||||
C[175]="是否更新基础配置?(不影响节点配置,仅重置 log、outbounds、endpoints、route、experimental、dns、ntp、http_clients)[Y/n]:"
|
C[175]="是否更新基础配置?(不影响节点配置,仅重置 log、outbounds、endpoints、route、experimental、dns、ntp、http_clients)[Y/n]:"
|
||||||
|
E[176]="Enable subscription"
|
||||||
|
C[176]="开启订阅"
|
||||||
|
E[177]="Disable subscription"
|
||||||
|
C[177]="关闭订阅"
|
||||||
|
|
||||||
# 自定义字体彩色,read 函数
|
# 自定义字体彩色,read 函数
|
||||||
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
|
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
|
||||||
@@ -631,16 +635,16 @@ input_cdn() {
|
|||||||
# 输入 UUID
|
# 输入 UUID
|
||||||
input_uuid() {
|
input_uuid() {
|
||||||
# 输入 UUID ,错误超过 5 次将会退出
|
# 输入 UUID ,错误超过 5 次将会退出
|
||||||
UUID_DEFAULT=$(cat /proc/sys/kernel/random/uuid)
|
local UUID_DEFAULT=$(cat /proc/sys/kernel/random/uuid)
|
||||||
[[ "$IS_FAST_INSTALL" = 'is_fast_install' || "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ]] && UUID_CONFIRM=${UUID_CONFIRM:-"$UUID_DEFAULT"}
|
[[ "$IS_FAST_INSTALL" = 'is_fast_install' || "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ]] && UUID_CONFIRM=${UUID_CONFIRM:-"$UUID_DEFAULT"}
|
||||||
if [ -z "$UUID_CONFIRM" ]; then
|
if [ -z "$UUID_CONFIRM" ]; then
|
||||||
(( STEP_NUM++ )) || true
|
(( STEP_NUM++ )) || true
|
||||||
reading "\n ${TOTAL_STEPS:+(${STEP_NUM}/${TOTAL_STEPS}) } $(text 12) " UUID_CONFIRM
|
reading "\n ${TOTAL_STEPS:+(${STEP_NUM}/${TOTAL_STEPS}) }$(text 12) " UUID_CONFIRM
|
||||||
fi
|
fi
|
||||||
local UUID_ERROR_TIME=5
|
local UUID_ERROR_TIME=5
|
||||||
until [[ -z "$UUID_CONFIRM" || "${UUID_CONFIRM,,}" =~ ^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$ ]]; do
|
until [[ -z "$UUID_CONFIRM" || "${UUID_CONFIRM,,}" =~ ^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$ ]]; do
|
||||||
(( UUID_ERROR_TIME-- )) || true
|
(( UUID_ERROR_TIME-- )) || true
|
||||||
[ "$UUID_ERROR_TIME" = 0 ] && error "\n $(text 3) \n" || reading "\n $(text 4) \n" UUID_CONFIRM
|
[ "$UUID_ERROR_TIME" = 0 ] && error "\n $(text 3) \n" || reading "\n $(text 4) " UUID_CONFIRM
|
||||||
done
|
done
|
||||||
UUID_CONFIRM=${UUID_CONFIRM:-"$UUID_DEFAULT"}
|
UUID_CONFIRM=${UUID_CONFIRM:-"$UUID_DEFAULT"}
|
||||||
}
|
}
|
||||||
@@ -686,6 +690,14 @@ change_config() {
|
|||||||
local BIND_IFACE_NOW=$(awk -F '"' '/"bind_interface"[[:space:]]*:[[:space:]]*"/{print $4}' "${WORK_DIR}/conf/01_outbounds.json" 2>/dev/null)
|
local BIND_IFACE_NOW=$(awk -F '"' '/"bind_interface"[[:space:]]*:[[:space:]]*"/{print $4}' "${WORK_DIR}/conf/01_outbounds.json" 2>/dev/null)
|
||||||
MENU_IDX+=(169) && MENU_KEY+=(bindinterface) && MENU_VAL+=("${BIND_IFACE_NOW:-default}")
|
MENU_IDX+=(169) && MENU_KEY+=(bindinterface) && MENU_VAL+=("${BIND_IFACE_NOW:-default}")
|
||||||
|
|
||||||
|
# 订阅开关(基于 nginx.conf 文件内容检测)
|
||||||
|
if [ -s "${WORK_DIR}/nginx.conf" ] && \
|
||||||
|
grep -qE 'location ~ \^/[^/]+/auto \{' "${WORK_DIR}/nginx.conf" 2>/dev/null; then
|
||||||
|
MENU_IDX+=(177) && MENU_KEY+=(subscribe) && MENU_VAL+=("$(text 177)")
|
||||||
|
else
|
||||||
|
MENU_IDX+=(176) && MENU_KEY+=(subscribe) && MENU_VAL+=("$(text 176)")
|
||||||
|
fi
|
||||||
|
|
||||||
# Hysteria2 带宽和端口跳跃(仅在 Hysteria2 已安装时显示)
|
# Hysteria2 带宽和端口跳跃(仅在 Hysteria2 已安装时显示)
|
||||||
if ls ${WORK_DIR}/conf/*_${NODE_TAG[1]}_inbounds.json >/dev/null 2>&1; then
|
if ls ${WORK_DIR}/conf/*_${NODE_TAG[1]}_inbounds.json >/dev/null 2>&1; then
|
||||||
local HY2_LINE=$(grep 'type: hysteria2' ${WORK_DIR}/subscribe/proxies)
|
local HY2_LINE=$(grep 'type: hysteria2' ${WORK_DIR}/subscribe/proxies)
|
||||||
@@ -728,7 +740,7 @@ change_config() {
|
|||||||
local _val="${MENU_VAL[_i]}"
|
local _val="${MENU_VAL[_i]}"
|
||||||
local _raw
|
local _raw
|
||||||
eval "_raw=\"\${${L}[${MENU_IDX[_i]}]}\""
|
eval "_raw=\"\${${L}[${MENU_IDX[_i]}]}\""
|
||||||
eval "hint \" $(( _i+1 )). ${_raw}\""
|
eval "hint \" $(printf '%2d' $(( _i+1 ))). ${_raw}\""
|
||||||
done
|
done
|
||||||
hint ""
|
hint ""
|
||||||
reading " $(text 24) " CHOOSE_NODE_INFO
|
reading " $(text 24) " CHOOSE_NODE_INFO
|
||||||
@@ -761,7 +773,7 @@ change_config() {
|
|||||||
[ -s ${WORK_DIR}/conf/${CONF_FILES[a]} ] && sed -i "s/\(.*listen_port.*:\)$((OLD_START_PORT+a))/\1$((START_PORT+a))/" ${WORK_DIR}/conf/*
|
[ -s ${WORK_DIR}/conf/${CONF_FILES[a]} ] && sed -i "s/\(.*listen_port.*:\)$((OLD_START_PORT+a))/\1$((START_PORT+a))/" ${WORK_DIR}/conf/*
|
||||||
done
|
done
|
||||||
fetch_nodes_value
|
fetch_nodes_value
|
||||||
[ -n "$PORT_NGINX" ] && UUID_CONFIRM=$(awk '/location/ && /\// {match($0, /\/([^ \/]+)/, arr); p=arr[1]; sub(/-(vmess|vless|auto2|auto).*/, "", p); print p; exit}' ${WORK_DIR}/nginx.conf) && export_nginx_conf_file
|
[ -n "$PORT_NGINX" ] && export_nginx_conf_file
|
||||||
cmd_systemctl reload sing-box
|
cmd_systemctl reload sing-box
|
||||||
[ -n "$ARGO_DOMAIN" ] && export_argo_json_file
|
[ -n "$ARGO_DOMAIN" ] && export_argo_json_file
|
||||||
sync_firewall_rules
|
sync_firewall_rules
|
||||||
@@ -920,6 +932,64 @@ change_config() {
|
|||||||
cmd_systemctl reload sing-box
|
cmd_systemctl reload sing-box
|
||||||
export_list
|
export_list
|
||||||
return
|
return
|
||||||
|
elif [ "$KEY" = "subscribe" ]; then
|
||||||
|
# 订阅开关 — 检测 nginx.conf 中是否存在订阅分发 location 块
|
||||||
|
if grep -qE 'location ~ \^/[^/]+/auto \{' "${WORK_DIR}/nginx.conf" 2>/dev/null; then
|
||||||
|
# 已开启 → 关闭订阅
|
||||||
|
info "\n $(text 177) "
|
||||||
|
# 检测 Argo 真实状态(Alpine 和 systemd 通用:检查守护进程文件是否存在)
|
||||||
|
[ -s ${ARGO_DAEMON_FILE} ] && IS_ARGO=is_argo || IS_ARGO=no_argo
|
||||||
|
# 从旧 nginx.conf 读取 PORT_NGINX(确定文件存在,无需条件判断)
|
||||||
|
PORT_NGINX=$(awk '/listen/{print $2; exit}' ${WORK_DIR}/nginx.conf)
|
||||||
|
IS_SUB=no_sub
|
||||||
|
fetch_nodes_value
|
||||||
|
# 判断是否还需要 nginx:有 WS 协议且 Argo 反代
|
||||||
|
if { [ -n "$PORT_VMESS_WS" ] || [ -n "$PORT_VLESS_WS" ]; } && [ "$IS_ARGO" = 'is_argo' ]; then
|
||||||
|
export_nginx_conf_file
|
||||||
|
nginx -s reload -c ${WORK_DIR}/nginx.conf 2>/dev/null || nginx_run
|
||||||
|
else
|
||||||
|
nginx_stop
|
||||||
|
[ "$SYSTEM" != 'Alpine' ] && [ "$IS_CENTOS" != 'CentOS7' ] && \
|
||||||
|
sed -i '/ExecStartPre=.*nginx/d' ${SINGBOX_DAEMON_FILE} && systemctl daemon-reload
|
||||||
|
rm -f ${WORK_DIR}/nginx.conf
|
||||||
|
unset PORT_NGINX
|
||||||
|
fi
|
||||||
|
/bin/rm -f ${WORK_DIR}/subscribe/qr
|
||||||
|
export_list
|
||||||
|
info " $(text 112) "
|
||||||
|
else
|
||||||
|
# 未开启 → 开启订阅
|
||||||
|
info "\n $(text 176) "
|
||||||
|
IS_SUB=is_sub
|
||||||
|
# 确保 nginx 已安装
|
||||||
|
if ! command -v nginx >/dev/null 2>&1; then
|
||||||
|
info "\n $(text 7) nginx"
|
||||||
|
${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
check_arch
|
||||||
|
[ ! -e "${WORK_DIR}/qrencode" ] && \
|
||||||
|
wget --no-check-certificate --continue -qO ${WORK_DIR}/qrencode \
|
||||||
|
${GH_PROXY}https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH 2>/dev/null \
|
||||||
|
&& chmod +x ${WORK_DIR}/qrencode
|
||||||
|
fetch_nodes_value
|
||||||
|
[ -z "$PORT_NGINX" ] && input_nginx_port
|
||||||
|
export_nginx_conf_file
|
||||||
|
# 更新服务文件 ExecStartPre(非 CentOS7)
|
||||||
|
if [ "$SYSTEM" != 'Alpine' ] && [ "$IS_CENTOS" != 'CentOS7' ] && \
|
||||||
|
! grep -q 'ExecStartPre=.*nginx' ${SINGBOX_DAEMON_FILE} 2>/dev/null; then
|
||||||
|
sed -i '/^ExecStart=/i ExecStartPre='$(command -v nginx)' -c '${WORK_DIR}'/nginx.conf' ${SINGBOX_DAEMON_FILE}
|
||||||
|
systemctl daemon-reload
|
||||||
|
fi
|
||||||
|
# 启动或 reload nginx
|
||||||
|
if ps -eo pid,args | grep -qE "[n]ginx.*${WORK_DIR}/nginx.conf" 2>/dev/null; then
|
||||||
|
nginx -s reload -c ${WORK_DIR}/nginx.conf 2>/dev/null || true
|
||||||
|
else
|
||||||
|
nginx_run
|
||||||
|
fi
|
||||||
|
export_list
|
||||||
|
info " $(text 112) "
|
||||||
|
fi
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
hint ""
|
hint ""
|
||||||
@@ -2062,16 +2132,18 @@ check_install() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Nginx 启动/停止函数(全局定义,供 cmd_systemctl() 和 change_config() 共用)
|
||||||
|
nginx_run() {
|
||||||
|
$(command -v nginx) -c $WORK_DIR/nginx.conf
|
||||||
|
}
|
||||||
|
|
||||||
|
nginx_stop() {
|
||||||
|
local NGINX_PID=$(ps -eo pid,args | awk -v work_dir="$WORK_DIR" '$0~(work_dir"/nginx.conf"){print $1;exit}')
|
||||||
|
ss -nltp | sed -n "/pid=$NGINX_PID,/ s/,/ /gp" | grep -oP 'pid=\K\S+' | sort -u | xargs kill -9 >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
# 为了适配 alpine,定义 cmd_systemctl 的函数
|
# 为了适配 alpine,定义 cmd_systemctl 的函数
|
||||||
cmd_systemctl() {
|
cmd_systemctl() {
|
||||||
nginx_run() {
|
|
||||||
$(command -v nginx) -c $WORK_DIR/nginx.conf
|
|
||||||
}
|
|
||||||
|
|
||||||
nginx_stop() {
|
|
||||||
local NGINX_PID=$(ps -eo pid,args | awk -v work_dir="$WORK_DIR" '$0~(work_dir"/nginx.conf"){print $1;exit}')
|
|
||||||
ss -nltp | sed -n "/pid=$NGINX_PID,/ s/,/ /gp" | grep -oP 'pid=\K\S+' | sort -u | xargs kill -9 >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$SYSTEM" = 'Alpine' ]; then
|
if [ "$SYSTEM" = 'Alpine' ]; then
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -4392,10 +4464,17 @@ fetch_nodes_value() {
|
|||||||
# 如有 Argo,获取 Argo Tunnel
|
# 如有 Argo,获取 Argo Tunnel
|
||||||
[[ ${STATUS[1]} =~ $(text 27)|$(text 28) ]] && grep -q '\--url' ${ARGO_DAEMON_FILE} && { cmd_systemctl enable argo; sleep 2 && cmd_systemctl status argo &>/dev/null && fetch_quicktunnel_domain; }
|
[[ ${STATUS[1]} =~ $(text 27)|$(text 28) ]] && grep -q '\--url' ${ARGO_DAEMON_FILE} && { cmd_systemctl enable argo; sleep 2 && cmd_systemctl status argo &>/dev/null && fetch_quicktunnel_domain; }
|
||||||
|
|
||||||
# 获取 Nginx 端口和路径
|
# 获取 UUID_CONFIRM(从 JSON 配置文件读取,不依赖 nginx)
|
||||||
[[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && local NGINX_JSON=$(cat ${WORK_DIR}/nginx.conf) &&
|
# 如 UUID_CONFIRM 已有值(例如上层已交互输入),跳过 JSON 读取,避免重复弹窗
|
||||||
PORT_NGINX=$(awk '/listen/{print $2; exit}' <<< "$NGINX_JSON") &&
|
[ -z "$UUID_CONFIRM" ] && UUID_CONFIRM=$(awk 'match($0, /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/) { print substr($0, RSTART, RLENGTH); exit }' ${WORK_DIR}/conf/1*.json 2>/dev/null)
|
||||||
UUID_CONFIRM=$(grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' <<< "$NGINX_JSON" | sed -n '1p')
|
# JSON 中提取不到时,尝试从 nginx.conf 提取(订阅开启 / 关闭时 nginx.conf 一定含有 UUID)
|
||||||
|
[ -z "$UUID_CONFIRM" ] && [ -s "${WORK_DIR}/nginx.conf" ] && \
|
||||||
|
UUID_CONFIRM=$(awk 'match($0, /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/) { print substr($0, RSTART, RLENGTH); exit }' ${WORK_DIR}/nginx.conf 2>/dev/null)
|
||||||
|
# 提取不到时,走交互式输入(与新安装一致:默认随机 UUID,回车使用默认值)
|
||||||
|
[ -z "$UUID_CONFIRM" ] && input_uuid
|
||||||
|
# 获取 Nginx 端口(首次开启订阅时 nginx.conf 尚未创建,静默跳过)
|
||||||
|
[[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && [ -s "${WORK_DIR}/nginx.conf" ] &&
|
||||||
|
PORT_NGINX=$(awk '/listen/{print $2; exit}' ${WORK_DIR}/nginx.conf)
|
||||||
|
|
||||||
# 获取 XTLS + Reality key-value
|
# 获取 XTLS + Reality key-value
|
||||||
[ -s ${WORK_DIR}/conf/*_${NODE_TAG[0]}_inbounds.json ] && local JSON=$(cat ${WORK_DIR}/conf/*_${NODE_TAG[0]}_inbounds.json) && NODE_NAME[11]=$(sed -n "s/.*\"tag\":\"\(.*\) ${NODE_TAG[0]}.*/\1/p" <<< "$JSON") && PORT_XTLS_REALITY=$(sed -n 's/.*"listen_port":\([0-9]\+\),/\1/gp' <<< "$JSON") && UUID[11]=$(awk -F '"' '/"uuid"/{print $4}' <<< "$JSON") && REALITY_PRIVATE[11]=$(awk -F '"' '/"private_key"/{print $4}' <<< "$JSON") && REALITY_PUBLIC[11]=$(awk -F '"' '/"public_key"/{print $4}' <<< "$JSON")
|
[ -s ${WORK_DIR}/conf/*_${NODE_TAG[0]}_inbounds.json ] && local JSON=$(cat ${WORK_DIR}/conf/*_${NODE_TAG[0]}_inbounds.json) && NODE_NAME[11]=$(sed -n "s/.*\"tag\":\"\(.*\) ${NODE_TAG[0]}.*/\1/p" <<< "$JSON") && PORT_XTLS_REALITY=$(sed -n 's/.*"listen_port":\([0-9]\+\),/\1/gp' <<< "$JSON") && UUID[11]=$(awk -F '"' '/"uuid"/{print $4}' <<< "$JSON") && REALITY_PRIVATE[11]=$(awk -F '"' '/"private_key"/{print $4}' <<< "$JSON") && REALITY_PUBLIC[11]=$(awk -F '"' '/"public_key"/{print $4}' <<< "$JSON")
|
||||||
@@ -5345,15 +5424,6 @@ change_protocols() {
|
|||||||
# 获取各节点信息
|
# 获取各节点信息
|
||||||
fetch_nodes_value
|
fetch_nodes_value
|
||||||
|
|
||||||
# 用于新节点的配置信息
|
|
||||||
if [ "${#UUID[@]}" -gt 0 ]; then
|
|
||||||
UUID_CONFIRM="$(printf "%s\n" "${UUID[@]}" | grep -m 1 . )"
|
|
||||||
elif grep -q '.' <<< "${TROJAN_PASSWORD}"; then
|
|
||||||
UUID_CONFIRM="${TROJAN_PASSWORD}"
|
|
||||||
else
|
|
||||||
input_uuid
|
|
||||||
fi
|
|
||||||
|
|
||||||
for v in "${NODE_NAME[@]}"; do
|
for v in "${NODE_NAME[@]}"; do
|
||||||
[ -n "$v" ] && NODE_NAME_CONFIRM="$v" && break
|
[ -n "$v" ] && NODE_NAME_CONFIRM="$v" && break
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user