mirror of
https://github.com/fscarmen/sing-box.git
synced 2026-08-10 17:55:16 +08:00
v1.3.17 feat: add SIGHUP hot-reload support, replace restart sequences with reload
- special thanks to @starfendou for the technical guidance on hot reloading. - add `cmd_systemctl reload` subcommand with PID detection (Alpine: pidfile → kill -HUP; systemd: systemctl kill -s HUP) - add OpenRC `reload()` function in sing-box service via start-stop-daemon --signal HUP - replace `restart` with `reload` for config changes (ports, hy2realm, bindinterface, uuid/sni/name) - replace `disable+enable` with `reload` for protocol add/remove and port change flows - replace `restart` with `reload` for custom route add/delete operations - remove unnecessary `sync_firewall_rules` call in hy2bw bandwidth change (only modifies subscribe/proxies, no port changes) - run `sing-box check -C` with the new binary before replacing the running one. abort upgrade early when the new binary rejects the existing config - force base-config regeneration on upgrade to guarantee sing-box check passes v1.3.17 feat: 新增 SIGHUP 热更支持,用 reload 替换重启流程 - 感谢 @starfendou 在热加载(Hot Reloading)技术上给予的指导与支持。 - cmd_systemctl 新增 reload 子命令,支持 PID 检测(Alpine: pidfile → kill -HUP; systemd: systemctl kill -s HUP) - OpenRC 服务脚本新增 reload() 函数,通过 start-stop-daemon --signal HUP 实现热更 - 端口 / hy2realm / 绑定接口 / 通用配置修改改为 reload - 协议增删和端口变更流程从 disable+enable 改为 reload - 自定义路由增删改为 reload - 移除 hy2bw 带宽修改中无意义的 sync_firewall_rules 调用(只改 subscribe/proxies,不涉及端口) - 替换运行中二进制前,先用新内核执行 `sing-box check -C` 预检配置,新内核不兼容现有配置时提前中止升级 - 升级时强制重置基础配置至新版格式,保证兼容性
This commit is contained in:
@@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
* * *
|
* * *
|
||||||
## 1.更新信息
|
## 1.更新信息
|
||||||
|
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.07.01 v1.3.15 Add v2rayN Finalmask field for hysteria2 realm subscription output; v2rayN 订阅输出增加 Hysteria2 Realm 的 Finalmask 字段
|
||||||
|
|||||||
+123
-100
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# 当前脚本版本号
|
# 当前脚本版本号
|
||||||
VERSION='v1.3.16 (2026.07.16)'
|
VERSION='v1.3.17 (2026.07.20)'
|
||||||
|
|
||||||
# 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"
|
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"
|
||||||
C[1]="1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj"
|
C[1]="1. sb -d 菜单新增「指定网络出口」选项,可为出站流量绑定特定网卡; 2. v2rayN 的 Hysteria2 Realm 配置从 Finalmask 字段改为 ProtoExtraObj; 3. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 4. 新增 SIGHUP 热更支持,用 reload 替换重启流程; 4. 升级时强制重置基础配置至新版格式,保证兼容性"
|
||||||
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."
|
||||||
@@ -146,8 +146,8 @@ E[52]="Please set the ip \[\${WS_SERVER_IP_SHOW}] to domain \[\${TYPE_HOST_DOMAI
|
|||||||
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]=""
|
E[54]="Configuration check failed, new version \$ONLINE is incompatible with current config."
|
||||||
C[54]=""
|
C[54]="配置文件检查失败,新版本 \$ONLINE 与当前配置不兼容"
|
||||||
E[55]="The script runs today: \$TODAY. Total: \$TOTAL"
|
E[55]="The script runs today: \$TODAY. Total: \$TOTAL"
|
||||||
C[55]="脚本当天运行次数: \$TODAY,累计运行次数: \$TOTAL"
|
C[55]="脚本当天运行次数: \$TODAY,累计运行次数: \$TOTAL"
|
||||||
E[56]="Process ID"
|
E[56]="Process ID"
|
||||||
@@ -262,8 +262,8 @@ E[110]="No CDN protocol is currently in use"
|
|||||||
C[110]="当前没有使用 CDN 的协议"
|
C[110]="当前没有使用 CDN 的协议"
|
||||||
E[111]="Please select or enter a new CDN (press Enter to keep the current one):"
|
E[111]="Please select or enter a new CDN (press Enter to keep the current one):"
|
||||||
C[111]="请选择或输入新的 CDN (回车保持当前值):"
|
C[111]="请选择或输入新的 CDN (回车保持当前值):"
|
||||||
E[112]="Change complete, restarting service..."
|
E[112]="Change complete"
|
||||||
C[112]="修改完成,正在重启服务..."
|
C[112]="修改完成"
|
||||||
E[113]="Failed to change CDN, using random privateKey"
|
E[113]="Failed to change CDN, using random privateKey"
|
||||||
C[113]="privateKey 格式失败次数过多,已使用随机私钥"
|
C[113]="privateKey 格式失败次数过多,已使用随机私钥"
|
||||||
E[114]="Invalid privateKey format: expected a 43-character base64url-encoded string."
|
E[114]="Invalid privateKey format: expected a 43-character base64url-encoded string."
|
||||||
@@ -382,6 +382,12 @@ E[171]="1. Default (not specified)"
|
|||||||
C[171]="1. 默认(不指定)"
|
C[171]="1. 默认(不指定)"
|
||||||
E[172]="Bound interface updated to: "
|
E[172]="Bound interface updated to: "
|
||||||
C[172]="绑定接口已更新为: "
|
C[172]="绑定接口已更新为: "
|
||||||
|
E[173]="Hot reload successful (PID unchanged: \$MAINPID)"
|
||||||
|
C[173]="热加载成功(PID 未变: \$MAINPID)"
|
||||||
|
E[174]="Failed to update configuration. Please check manually. Suggestion: reinstall script"
|
||||||
|
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]:"
|
||||||
|
C[175]="是否更新基础配置?(不影响节点配置,仅重置 log、outbounds、endpoints、route、experimental、dns、ntp、http_clients)[Y/n]:"
|
||||||
|
|
||||||
# 自定义字体彩色,read 函数
|
# 自定义字体彩色,read 函数
|
||||||
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
|
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
|
||||||
@@ -751,18 +757,16 @@ change_config() {
|
|||||||
OLD_START_PORT=$(awk 'NR == 1 { min = $0 } { if ($0 < min) min = $0; count++ } END {print min}' <<< "$OLD_PORTS")
|
OLD_START_PORT=$(awk 'NR == 1 { min = $0 } { if ($0 < min) min = $0; count++ } END {print min}' <<< "$OLD_PORTS")
|
||||||
OLD_CONSECUTIVE_PORTS=$(awk 'END { print NR }' <<< "$OLD_PORTS")
|
OLD_CONSECUTIVE_PORTS=$(awk 'END { print NR }' <<< "$OLD_PORTS")
|
||||||
input_start_port $OLD_CONSECUTIVE_PORTS
|
input_start_port $OLD_CONSECUTIVE_PORTS
|
||||||
cmd_systemctl disable sing-box
|
|
||||||
for ((a=0; a<$OLD_CONSECUTIVE_PORTS; a++)) do
|
for ((a=0; a<$OLD_CONSECUTIVE_PORTS; a++)) do
|
||||||
[ -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" ] && 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
|
||||||
cmd_systemctl enable 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
|
||||||
sleep 2
|
sleep 2
|
||||||
export_list
|
export_list
|
||||||
cmd_systemctl status sing-box &>/dev/null && info " Sing-box $(text 121) $(text 37) " || error " Sing-box $(text 121) $(text 38) "
|
|
||||||
return
|
return
|
||||||
elif [ "$KEY" = "hy2bw" ]; then
|
elif [ "$KEY" = "hy2bw" ]; then
|
||||||
# 修改 Hysteria2 带宽
|
# 修改 Hysteria2 带宽
|
||||||
@@ -778,7 +782,6 @@ change_config() {
|
|||||||
warning " $(text 143) "
|
warning " $(text 143) "
|
||||||
done
|
done
|
||||||
sed -i -E "s/(up: \")([0-9]+)( Mbps\")/\1${HY2_UP}\3/g; s/(down: \")([0-9]+)( Mbps\")/\1${HY2_DOWN}\3/g" ${WORK_DIR}/subscribe/proxies
|
sed -i -E "s/(up: \")([0-9]+)( Mbps\")/\1${HY2_UP}\3/g; s/(down: \")([0-9]+)( Mbps\")/\1${HY2_DOWN}\3/g" ${WORK_DIR}/subscribe/proxies
|
||||||
sync_firewall_rules
|
|
||||||
hint " $(text 112) "
|
hint " $(text 112) "
|
||||||
export_list
|
export_list
|
||||||
return
|
return
|
||||||
@@ -799,8 +802,7 @@ change_config() {
|
|||||||
set_hy2_realm_config enable
|
set_hy2_realm_config enable
|
||||||
[ "$IS_HY2_WARP" = 'is_hy2_warp' ] && sync_hy2_warp_route enable || sync_hy2_warp_route disable
|
[ "$IS_HY2_WARP" = 'is_hy2_warp' ] && sync_hy2_warp_route enable || sync_hy2_warp_route disable
|
||||||
fi
|
fi
|
||||||
hint " $(text 112) "
|
cmd_systemctl reload sing-box
|
||||||
cmd_systemctl restart sing-box
|
|
||||||
export_list
|
export_list
|
||||||
return
|
return
|
||||||
elif [ "$KEY" = "hy2hopping" ]; then
|
elif [ "$KEY" = "hy2hopping" ]; then
|
||||||
@@ -915,9 +917,7 @@ change_config() {
|
|||||||
warning " Invalid selection " && return
|
warning " Invalid selection " && return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cmd_systemctl restart sing-box
|
cmd_systemctl reload sing-box
|
||||||
sleep 2
|
|
||||||
cmd_systemctl status sing-box &>/dev/null && info "\n Sing-box $(text 28) $(text 37) \n" || warning "\n Sing-box $(text 27) $(text 38) \n"
|
|
||||||
export_list
|
export_list
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -936,8 +936,6 @@ change_config() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 批量替换,更换服务IP和指纹不需重启服务
|
# 批量替换,更换服务IP和指纹不需重启服务
|
||||||
[[ ! "$KEY" =~ ^(fingerprint|serverip|cdn)$ ]] && hint " $(text 112) "
|
|
||||||
|
|
||||||
if [[ "$KEY" =~ ^(serverip|cdn)$ ]]; then
|
if [[ "$KEY" =~ ^(serverip|cdn)$ ]]; then
|
||||||
# IP 在配置里出现的形式有多种,逐一替换
|
# IP 在配置里出现的形式有多种,逐一替换
|
||||||
find ${WORK_DIR} -type f | xargs -P 50 sed -i -e "s|\"server\": \"${OLD}\"|\"server\": \"${NEW_VAL}\"|g; s|\"WS_SERVER_IP_SHOW\": \"${OLD}\"|\"WS_SERVER_IP_SHOW\": \"${NEW_VAL}\"|g" 2>/dev/null
|
find ${WORK_DIR} -type f | xargs -P 50 sed -i -e "s|\"server\": \"${OLD}\"|\"server\": \"${NEW_VAL}\"|g; s|\"WS_SERVER_IP_SHOW\": \"${OLD}\"|\"WS_SERVER_IP_SHOW\": \"${NEW_VAL}\"|g" 2>/dev/null
|
||||||
@@ -946,11 +944,7 @@ change_config() {
|
|||||||
find ${WORK_DIR}/subscribe -type f | xargs -P 50 sed -i "s|${OLD}|${NEW_VAL}|g" 2>/dev/null
|
find ${WORK_DIR}/subscribe -type f | xargs -P 50 sed -i "s|${OLD}|${NEW_VAL}|g" 2>/dev/null
|
||||||
else
|
else
|
||||||
find ${WORK_DIR} -type f | xargs -P 50 sed -i "s|${OLD}|${NEW_VAL}|g" 2>/dev/null
|
find ${WORK_DIR} -type f | xargs -P 50 sed -i "s|${OLD}|${NEW_VAL}|g" 2>/dev/null
|
||||||
if [[ ! "$KEY" =~ ^(fingerprint)$ ]]; then
|
[[ ! "$KEY" =~ ^(fingerprint)$ ]] && cmd_systemctl reload sing-box
|
||||||
cmd_systemctl restart sing-box
|
|
||||||
sleep 2
|
|
||||||
cmd_systemctl status sing-box &>/dev/null && info "\n Sing-box $(text 28) $(text 37) \n" || warning "\n Sing-box $(text 27) $(text 38) \n"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
export_list
|
export_list
|
||||||
}
|
}
|
||||||
@@ -1549,8 +1543,7 @@ custom_route_add() {
|
|||||||
custom_route_compact_rules
|
custom_route_compact_rules
|
||||||
|
|
||||||
info " $(text 157) "
|
info " $(text 157) "
|
||||||
hint " $(text 112) "
|
cmd_systemctl reload sing-box
|
||||||
cmd_systemctl restart sing-box
|
|
||||||
sleep 2
|
sleep 2
|
||||||
cmd_systemctl status sing-box &>/dev/null && \
|
cmd_systemctl status sing-box &>/dev/null && \
|
||||||
info "\n Sing-box $(text 28) $(text 37) \n" || \
|
info "\n Sing-box $(text 28) $(text 37) \n" || \
|
||||||
@@ -1690,8 +1683,7 @@ custom_route_delete() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
info " $(text 160) "
|
info " $(text 160) "
|
||||||
hint " $(text 112) "
|
cmd_systemctl reload sing-box
|
||||||
cmd_systemctl restart sing-box
|
|
||||||
sleep 2
|
sleep 2
|
||||||
cmd_systemctl status sing-box &>/dev/null && \
|
cmd_systemctl status sing-box &>/dev/null && \
|
||||||
info "\n Sing-box $(text 28) $(text 37) \n" || \
|
info "\n Sing-box $(text 28) $(text 37) \n" || \
|
||||||
@@ -2094,6 +2086,15 @@ cmd_systemctl() {
|
|||||||
restart )
|
restart )
|
||||||
rc-service "$2" restart >/dev/null 2>&1
|
rc-service "$2" restart >/dev/null 2>&1
|
||||||
;;
|
;;
|
||||||
|
reload )
|
||||||
|
local MAINPID=$(cat /var/run/sing-box.pid 2>/dev/null)
|
||||||
|
if [ -n "$MAINPID" ] && kill -0 "$MAINPID" 2>/dev/null; then
|
||||||
|
kill -HUP "$MAINPID" 2>/dev/null
|
||||||
|
info "\n $(text 173) \n"
|
||||||
|
else
|
||||||
|
rc-service "$2" restart >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
status )
|
status )
|
||||||
rc-service "$2" status
|
rc-service "$2" status
|
||||||
;;
|
;;
|
||||||
@@ -2116,6 +2117,15 @@ cmd_systemctl() {
|
|||||||
systemctl restart "$2" >/dev/null 2>&1
|
systemctl restart "$2" >/dev/null 2>&1
|
||||||
[ "$IS_CENTOS" = 'CentOS7' ] && [ "$2" = 'sing-box' ] && [ -s $WORK_DIR/nginx.conf ] && nginx_run
|
[ "$IS_CENTOS" = 'CentOS7' ] && [ "$2" = 'sing-box' ] && [ -s $WORK_DIR/nginx.conf ] && nginx_run
|
||||||
;;
|
;;
|
||||||
|
reload )
|
||||||
|
local MAINPID=$(systemctl show -p MainPID sing-box 2>/dev/null | awk -F= '{print $2}')
|
||||||
|
if [ -n "$MAINPID" ] && [ "$MAINPID" -gt 0 ] 2>/dev/null; then
|
||||||
|
systemctl kill -s HUP sing-box >/dev/null 2>&1
|
||||||
|
info "\n $(text 173) \n"
|
||||||
|
else
|
||||||
|
systemctl restart sing-box >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
status )
|
status )
|
||||||
systemctl is-active "$2"
|
systemctl is-active "$2"
|
||||||
;;
|
;;
|
||||||
@@ -3445,20 +3455,10 @@ http {
|
|||||||
echo "$NGINX_CONF" > ${WORK_DIR}/nginx.conf
|
echo "$NGINX_CONF" > ${WORK_DIR}/nginx.conf
|
||||||
}
|
}
|
||||||
|
|
||||||
# 生成 sing-box 配置文件
|
# 生成 sing-box 基础配置
|
||||||
sing-box_json() {
|
generate_sing_box_base_conf() {
|
||||||
local IS_CHANGE=$1
|
# 生成 log 配置
|
||||||
mkdir -p ${WORK_DIR}/conf ${WORK_DIR}/logs ${WORK_DIR}/subscribe
|
cat > ${WORK_DIR}/conf/00_log.json << EOF
|
||||||
|
|
||||||
# 判断是否为新安装,不为 change 就是新安装
|
|
||||||
if [ "$IS_CHANGE" = 'change' ]; then
|
|
||||||
# 判断 sing-box 主程序所在路径
|
|
||||||
DIR=${WORK_DIR}
|
|
||||||
else
|
|
||||||
DIR=$TEMP_DIR
|
|
||||||
|
|
||||||
# 生成 log 配置
|
|
||||||
cat > ${WORK_DIR}/conf/00_log.json << EOF
|
|
||||||
{
|
{
|
||||||
"log":{
|
"log":{
|
||||||
"disabled":false,
|
"disabled":false,
|
||||||
@@ -3469,8 +3469,8 @@ sing-box_json() {
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 生成 outbound 配置
|
# 生成 outbound 配置
|
||||||
cat > ${WORK_DIR}/conf/01_outbounds.json << EOF
|
cat > ${WORK_DIR}/conf/01_outbounds.json << EOF
|
||||||
{
|
{
|
||||||
"outbounds":[
|
"outbounds":[
|
||||||
{
|
{
|
||||||
@@ -3482,8 +3482,8 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 生成 endpoint 配置
|
# 生成 endpoint 配置
|
||||||
cat > ${WORK_DIR}/conf/02_endpoints.json << EOF
|
cat > ${WORK_DIR}/conf/02_endpoints.json << EOF
|
||||||
{
|
{
|
||||||
"endpoints":[
|
"endpoints":[
|
||||||
{
|
{
|
||||||
@@ -3516,8 +3516,8 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 生成 route 配置
|
# 生成 route 配置
|
||||||
cat > ${WORK_DIR}/conf/03_route.json << EOF
|
cat > ${WORK_DIR}/conf/03_route.json << EOF
|
||||||
{
|
{
|
||||||
"route":{
|
"route":{
|
||||||
"default_http_client": "http-client-direct",
|
"default_http_client": "http-client-direct",
|
||||||
@@ -3554,15 +3554,15 @@ EOF
|
|||||||
"rule_set":[
|
"rule_set":[
|
||||||
"geosite-openai"
|
"geosite-openai"
|
||||||
],
|
],
|
||||||
"outbound":"${CHATGPT_OUT}"
|
"outbound":"${CHATGPT_OUT:-direct}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 生成缓存文件
|
# 生成缓存文件
|
||||||
cat > ${WORK_DIR}/conf/04_experimental.json << EOF
|
cat > ${WORK_DIR}/conf/04_experimental.json << EOF
|
||||||
{
|
{
|
||||||
"experimental": {
|
"experimental": {
|
||||||
"cache_file": {
|
"cache_file": {
|
||||||
@@ -3573,8 +3573,8 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 生成 dns 配置文件
|
# 生成 dns 配置文件
|
||||||
cat > ${WORK_DIR}/conf/05_dns.json << EOF
|
cat > ${WORK_DIR}/conf/05_dns.json << EOF
|
||||||
{
|
{
|
||||||
"dns":{
|
"dns":{
|
||||||
"servers":[
|
"servers":[
|
||||||
@@ -3588,8 +3588,8 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 内建的 NTP 客户端服务配置文件,这对于无法进行时间同步的环境很有用
|
# 内建的 NTP 客户端服务配置文件,这对于无法进行时间同步的环境很有用
|
||||||
cat > ${WORK_DIR}/conf/06_ntp.json << EOF
|
cat > ${WORK_DIR}/conf/06_ntp.json << EOF
|
||||||
{
|
{
|
||||||
"ntp": {
|
"ntp": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@@ -3600,8 +3600,8 @@ EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 专门给 sing-box 内部组件发 HTTP 请求用,比如这些场景会用到它:下载远程 rule_set:.srs 规则文件,ACME 申请证书,Cloudflare Origin CA 证书提供器,DERP / Tailscale 相关 HTTP 请求
|
# 专门给 sing-box 内部组件发 HTTP 请求用,比如这些场景会用到它:下载远程 rule_set:.srs 规则文件,ACME 申请证书,Cloudflare Origin CA 证书提供器,DERP / Tailscale 相关 HTTP 请求
|
||||||
cat > ${WORK_DIR}/conf/07_http_clients.json << EOF
|
cat > ${WORK_DIR}/conf/07_http_clients.json << EOF
|
||||||
{
|
{
|
||||||
"http_clients": [
|
"http_clients": [
|
||||||
{
|
{
|
||||||
@@ -3610,6 +3610,20 @@ EOF
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成 sing-box 配置文件
|
||||||
|
sing-box_json() {
|
||||||
|
local IS_CHANGE=$1
|
||||||
|
mkdir -p ${WORK_DIR}/conf ${WORK_DIR}/logs ${WORK_DIR}/subscribe
|
||||||
|
|
||||||
|
# 判断是否为新安装,不为 change 就是新安装
|
||||||
|
if [ "$IS_CHANGE" = 'change' ]; then
|
||||||
|
# 判断 sing-box 主程序所在路径
|
||||||
|
DIR=${WORK_DIR}
|
||||||
|
else
|
||||||
|
DIR=$TEMP_DIR
|
||||||
|
generate_sing_box_base_conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 生成 Reality 公私钥,第一次安装的时候,如有指定的私钥,则使用该私钥及生成对应的公钥;如没有指定私钥则使用新生成的;添加协议的时,使用相应数组里的第一个非空值,如全空则像第一次安装那样使用新生成的
|
# 生成 Reality 公私钥,第一次安装的时候,如有指定的私钥,则使用该私钥及生成对应的公钥;如没有指定私钥则使用新生成的;添加协议的时,使用相应数组里的第一个非空值,如全空则像第一次安装那样使用新生成的
|
||||||
@@ -4224,10 +4238,16 @@ depend() {
|
|||||||
[ -n "$PORT_NGINX" ] && OPENRC_SERVICE+="
|
[ -n "$PORT_NGINX" ] && OPENRC_SERVICE+="
|
||||||
need nginx"
|
need nginx"
|
||||||
|
|
||||||
# 添加 start_pre 函数,确保目录存在并设置正确权限
|
# 添加 reload 函数,支持 SIGHUP 热更
|
||||||
OPENRC_SERVICE+="
|
OPENRC_SERVICE+="
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
ebegin \"Reloading \${RC_SVCNAME}\"
|
||||||
|
start-stop-daemon --signal HUP --pidfile \$pidfile
|
||||||
|
eend \$? \"Failed to reload \${RC_SVCNAME}\"
|
||||||
|
}
|
||||||
|
|
||||||
start_pre() {
|
start_pre() {
|
||||||
# 确保日志目录和PID目录存在并有正确权限
|
# 确保日志目录和PID目录存在并有正确权限
|
||||||
mkdir -p ${WORK_DIR}/logs
|
mkdir -p ${WORK_DIR}/logs
|
||||||
@@ -5583,9 +5603,6 @@ change_protocols() {
|
|||||||
unset PORT_NAIVE
|
unset PORT_NAIVE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 停止 sing-box 服务
|
|
||||||
cmd_systemctl disable sing-box
|
|
||||||
|
|
||||||
# 生成 Nginx 配置文件
|
# 生成 Nginx 配置文件
|
||||||
[ -n "$PORT_NGINX" ] && export_nginx_conf_file
|
[ -n "$PORT_NGINX" ] && export_nginx_conf_file
|
||||||
|
|
||||||
@@ -5610,8 +5627,8 @@ change_protocols() {
|
|||||||
# 如有需要,删除 nginx 配置文件
|
# 如有需要,删除 nginx 配置文件
|
||||||
! ls ${ARGO_DAEMON_FILE} >/dev/null 2>&1 && [[ -s ${WORK_DIR}/nginx.conf && "$IS_SUB" = 'no_sub' ]] && IS_ARGO=no_argo && rm -f ${WORK_DIR}/nginx.conf
|
! ls ${ARGO_DAEMON_FILE} >/dev/null 2>&1 && [[ -s ${WORK_DIR}/nginx.conf && "$IS_SUB" = 'no_sub' ]] && IS_ARGO=no_argo && rm -f ${WORK_DIR}/nginx.conf
|
||||||
|
|
||||||
# 运行 sing-box
|
# 热更 sing-box(SIGHUP 重新加载配置,PID 不变)
|
||||||
cmd_systemctl enable sing-box
|
cmd_systemctl reload sing-box
|
||||||
|
|
||||||
# 打开防火墙相关端口
|
# 打开防火墙相关端口
|
||||||
sync_firewall_rules
|
sync_firewall_rules
|
||||||
@@ -5621,17 +5638,6 @@ change_protocols() {
|
|||||||
|
|
||||||
# 再次检测状态,运行 sing-box
|
# 再次检测状态,运行 sing-box
|
||||||
check_install
|
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
|
|
||||||
|
|
||||||
# 导出节点和订阅服务信息
|
# 导出节点和订阅服务信息
|
||||||
export_list
|
export_list
|
||||||
@@ -5669,38 +5675,55 @@ version() {
|
|||||||
check_system_info
|
check_system_info
|
||||||
wget --no-check-certificate --continue ${GH_PROXY}https://github.com/SagerNet/sing-box/releases/download/v$ONLINE/sing-box-$ONLINE-linux-$SING_BOX_ARCH.tar.gz -qO- | tar xz -C $TEMP_DIR sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box
|
wget --no-check-certificate --continue ${GH_PROXY}https://github.com/SagerNet/sing-box/releases/download/v$ONLINE/sing-box-$ONLINE-linux-$SING_BOX_ARCH.tar.gz -qO- | tar xz -C $TEMP_DIR sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box
|
||||||
|
|
||||||
if [ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ]; then
|
[ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ] || error "\n $(text 42) \n"
|
||||||
cmd_systemctl disable sing-box
|
if ! $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box check -C ${WORK_DIR}/conf >/dev/null; then
|
||||||
|
warning "\n $(text 54) " && reading "\n $(text 175) " UPDATE_CONFIG
|
||||||
|
[ "${UPDATE_CONFIG,,}" = 'n' ] && exit 1
|
||||||
|
|
||||||
# 备份旧版本
|
# 设置基础配置参数 dns.servers.prefer_go 和 dns.strategy
|
||||||
cp ${WORK_DIR}/sing-box ${WORK_DIR}/sing-box.bak
|
local STRATEGY=$(grep -E --exclude="03_route.json" 'ipv4_only|ipv6_only|prefer_ipv4|prefer_ipv6' ${WORK_DIR}/conf/0*.json | awk -F '"' '{print $(NF-1); exit}')
|
||||||
hint "\n $(text 102) \n"
|
STRATEGY=${STRATEGY:-prefer_ipv4}
|
||||||
|
command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet systemd-resolved && local IS_PREFER_GO=false || local IS_PREFER_GO=true
|
||||||
|
|
||||||
# 安装新版本
|
# 备份旧基础配置
|
||||||
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
|
for i in $(ls ${WORK_DIR}/conf/0*); do
|
||||||
|
cp $i ${i}.bak
|
||||||
|
done
|
||||||
|
generate_sing_box_base_conf
|
||||||
|
|
||||||
|
if ! $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box check -C ${WORK_DIR}/conf >/dev/null; then
|
||||||
|
for i in $(ls ${WORK_DIR}/conf/0*.bak); do
|
||||||
|
mv $i ${i%%.bak}
|
||||||
|
done
|
||||||
|
error "\n $(text 174) \n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 检查新版本是否成功运行
|
||||||
|
if cmd_systemctl status sing-box &>/dev/null; then
|
||||||
|
# 新版本运行成功,删除备份
|
||||||
|
rm -f ${WORK_DIR}/sing-box.bak ${WORK_DIR}/conf/*.bak
|
||||||
|
info "\n $(text 103) \n"
|
||||||
|
else
|
||||||
|
# 新版本运行失败,恢复旧版本
|
||||||
|
warning "\n $(text 104) \n"
|
||||||
|
mv ${WORK_DIR}/sing-box.bak ${WORK_DIR}/sing-box
|
||||||
|
rm -f ${WORK_DIR}/conf/*.bak
|
||||||
cmd_systemctl enable sing-box
|
cmd_systemctl enable sing-box
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
# 检查新版本是否成功运行
|
cmd_systemctl status sing-box &>/dev/null && info "\n $(text 105) \n" || error "\n $(text 106) \n"
|
||||||
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
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user