v1.2.16 Use OpenRC on Alpine to replace systemctl (Python3-compatible version).

This commit is contained in:
fscarmen
2025-04-07 02:01:40 +00:00
parent 712185c578
commit ee030a8e09
3 changed files with 475 additions and 192 deletions
+6 -3
View File
@@ -19,18 +19,21 @@
* * * * * *
## 1.更新信息 ## 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.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.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某个版本升级导致运行报错,增加强制指定版本号文件
<details> <details>
<summary>历史更新 history(点击即可展开或收起)</summary> <summary>历史更新 history(点击即可展开或收起)</summary>
<br> <br>
>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 >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 的端口跳跃 >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 的端口跳跃
+1 -1
View File
@@ -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}') 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" echo "$VERSION"
} }
+402 -122
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/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/' GH_PROXY='https://ghproxy.lvedong.eu.org/'
@@ -27,8 +27,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]="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." 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]="新增对 AnyTLS 协议的支持,感谢 [Betterdoitnow] 提供的配置。支持小火箭、Clash Mihomo、Sing-box 客户端输出" C[1]="1. 新增对 AnyTLS 协议的支持,感谢 [Betterdoitnow] 提供的配置。支持小火箭、Clash Mihomo、Sing-box 客户端输出; 2. 在 Alpine 系统中使用 OpenRC 取代兼容 Python3 的 systemctl 实现"
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."
@@ -229,6 +229,16 @@ E[100]="Can't get the official latest version. Script exits."
C[100]="获取不到官方的最新版本,脚本退出!" C[100]="获取不到官方的最新版本,脚本退出!"
E[101]="The contents of the AnyTLS configuration file need to be updated for the sing_box kernel." E[101]="The contents of the AnyTLS configuration file need to be updated for the sing_box kernel."
C[101]="AnyTLS 配置文件内容,需要更新 sing_box 内核" 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 函数 # 自定义字体彩色,read 函数
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色 warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
@@ -434,7 +444,10 @@ change_argo() {
error "\n $(text 61) " error "\n $(text 61) "
fi 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* ) *--config* )
ARGO_TYPE='Json' ARGO_TYPE='Json'
;; ;;
@@ -443,28 +456,34 @@ change_argo() {
;; ;;
* ) * )
ARGO_TYPE='Try' 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 esac
fetch_nodes_value fetch_nodes_value
hint "\n $(text 90) \n" hint "\n $(text 90) \n"
unset ARGO_DOMAIN unset ARGO_DOMAIN
hint " $(text 91) \n" && reading " $(text 24) " CHANGE_TO hint " $(text 91) \n" && reading " $(text 24) " CHANGE_TO
case "$CHANGE_TO" in case "$CHANGE_TO" in
1 ) 1 )
cmd_systemctl disable argo cmd_systemctl disable argo
[ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} [ -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
# 根据系统类型修改配置文件
[ "$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 ) 2 )
[ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml} [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.{json,yml}
input_argo_auth is_change_argo input_argo_auth is_change_argo
cmd_systemctl disable argo cmd_systemctl disable argo
if [ -n "$ARGO_TOKEN" ]; then 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 [ "$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 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 [ "$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 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/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 [ -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
;; ;;
@@ -472,7 +491,10 @@ change_argo() {
exit 0 exit 0
esac esac
# 启用 Argo 服务
cmd_systemctl enable argo cmd_systemctl enable argo
# 更新节点信息和配置
fetch_nodes_value fetch_nodes_value
export_nginx_conf_file export_nginx_conf_file
export_list export_list
@@ -513,11 +535,30 @@ check_install() {
[ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping [ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping
fi fi
# 检测是否安装其他 sing-box systemd 状态,和是否其他一键脚本 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
# 非 Alpine 系统使用 systemd 检查服务
if [ -s /etc/systemd/system/sing-box.service ]; then if [ -s /etc/systemd/system/sing-box.service ]; then
SYSTEMD_EXECSTART=$(grep '^ExecStart=' /etc/systemd/system/sing-box.service) SYSTEMD_EXECSTART=$(grep '^ExecStart=' /etc/systemd/system/sing-box.service)
case "$SYSTEMD_EXECSTART" in 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/' | '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) [ "$(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' ) 'ExecStart=/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json' )
@@ -533,7 +574,12 @@ check_install() {
SING_BOX_SCRIPT='FranzKafkaYu/sing-box-yes' && error "\n $(text 99) \n" 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" SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n"
fi
esac esac
elif [ -s /lib/systemd/system/sing-box.service ]; then elif [ -s /lib/systemd/system/sing-box.service ]; then
SYSTEMD_EXECSTART=$(grep '^ExecStart=' /lib/systemd/system/sing-box.service) SYSTEMD_EXECSTART=$(grep '^ExecStart=' /lib/systemd/system/sing-box.service)
@@ -542,11 +588,17 @@ check_install() {
SING_BOX_SCRIPT='233boy/sing-box' && error "\n $(text 99) \n" 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" SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n"
fi
esac esac
else else
STATUS[0]=$(text 26) STATUS[0]=$(text 26)
fi fi
fi
if [ "${STATUS[0]}" = "$(text 26)" ] && [ ! -s ${WORK_DIR}/sing-box ]; then if [ "${STATUS[0]}" = "$(text 26)" ] && [ ! -s ${WORK_DIR}/sing-box ]; then
{ {
@@ -567,9 +619,26 @@ check_install() {
fi fi
if [ "$NONINTERACTIVE_INSTALL" != 'noninteractive_install' ]; then 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 fi
if [ -s /etc/systemd/system/argo.service ]; then
# 检查 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) local ARGO_CONTENT=$(grep '^ExecStart' /etc/systemd/system/argo.service)
if grep -q '\--token' <<< "$ARGO_CONTENT"; then if grep -q '\--token' <<< "$ARGO_CONTENT"; then
ARGO_TYPE=is_token_argo ARGO_TYPE=is_token_argo
@@ -579,69 +648,58 @@ check_install() {
ARGO_TYPE=is_quicktunnel_argo ARGO_TYPE=is_quicktunnel_argo
fi fi
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; }& [[ "${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 的函数 # 为了适配 alpine,定义 cmd_systemctl 的函数
cmd_systemctl() { cmd_systemctl() {
local ENABLE_DISABLE=$1
local APP=$2
if [ "$ENABLE_DISABLE" = 'enable' ]; then
if [ "$SYSTEM" = 'Alpine' ]; then if [ "$SYSTEM" = 'Alpine' ]; then
systemctl start $APP case "$1" in
cat > /etc/local.d/$APP.start << EOF enable)
#!/usr/bin/env bash if [ "$2" = "sing-box" ]; then
rc-update add sing-box default >/dev/null 2>&1
systemctl start $APP rc-service sing-box start >/dev/null 2>&1
EOF elif [ "$2" = "argo" ]; then
chmod +x /etc/local.d/$APP.start rc-update add argo default >/dev/null 2>&1
rc-update add local >/dev/null 2>&1 rc-service argo start >/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
else
systemctl enable --now $APP
fi fi
elif [ "$ENABLE_DISABLE" = 'disable' ]; then ;;
if [ "$SYSTEM" = 'Alpine' ]; then disable)
systemctl stop $APP if [ "$2" = "sing-box" ]; then
[ "$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 rc-service sing-box stop >/dev/null 2>&1
rm -f /etc/local.d/$APP.start rc-update del sing-box default >/dev/null 2>&1
elif [ "$IS_CENTOS" = 'CentOS7' ]; then elif [ "$2" = "argo" ]; then
systemctl disable --now $APP rc-service argo stop >/dev/null 2>&1
[ "$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 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 else
systemctl disable --now $APP 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 "$@" >/dev/null 2>&1
fi fi
fi fi
} }
@@ -941,8 +999,8 @@ check_dependencies() {
if [ "$SYSTEM" = 'Alpine' ]; then if [ "$SYSTEM" = 'Alpine' ]; then
local CHECK_WGET=$(wget 2>&1 | head -n 1) local CHECK_WGET=$(wget 2>&1 | head -n 1)
grep -qi 'busybox' <<< "$CHECK_WGET" && ${PACKAGE_INSTALL[int]} wget >/dev/null 2>&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_CHECK=("bash" "rc-update" "virt-what" "iptables" "ip6tables")
local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3" "iptables" "ip6tables") local DEPS_INSTALL=("bash" "openrc" "virt-what" "iptables" "ip6tables")
for g in "${!DEPS_CHECK[@]}"; do for g in "${!DEPS_CHECK[@]}"; do
[ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS_ALPINE+=(${DEPS_INSTALL[g]}) [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS_ALPINE+=(${DEPS_INSTALL[g]})
done done
@@ -952,13 +1010,12 @@ check_dependencies() {
${PACKAGE_INSTALL[int]} ${DEPS_ALPINE[@]} >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} ${DEPS_ALPINE[@]} >/dev/null 2>&1
[[ -z "$VIRT" && "${DEPS_ALPINE[@]}" =~ 'virt-what' ]] && VIRT=$(virt-what | tr '\n' ' ') [[ -z "$VIRT" && "${DEPS_ALPINE[@]}" =~ 'virt-what' ]] && VIRT=$(virt-what | tr '\n' ' ')
fi 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 fi
# 检测 Linux 系统的依赖,升级库并重新安装依赖 # 检测 Linux 系统的依赖,升级库并重新安装依赖
local DEPS_CHECK=("wget" "tar" "systemctl" "ss" "bash" "openssl") local DEPS_CHECK=("wget" "tar" "ss" "bash" "openssl")
local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl") local DEPS_INSTALL=("wget" "tar" "iproute2" "bash" "openssl")
[ "$SYSTEM" != 'Alpine' ] && DEPS_CHECK+=("systemctl") && DEPS_INSTALL+=("systemctl")
for g in "${!DEPS_CHECK[@]}"; do for g in "${!DEPS_CHECK[@]}"; do
[ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS+=(${DEPS_INSTALL[g]}) [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS+=(${DEPS_INSTALL[g]})
done done
@@ -986,6 +1043,14 @@ check_dependencies() {
else else
info "\n $(text 8) \n" info "\n $(text 8) \n"
fi 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 # 检查并安装 nginx
@@ -994,8 +1059,9 @@ check_nginx() {
info "\n $(text 7) nginx \n" info "\n $(text 7) nginx \n"
${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_UPDATE[int]} >/dev/null 2>&1
${PACKAGE_INSTALL[int]} nginx >/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 fi
} }
@@ -1806,6 +1872,63 @@ EOF
# Sing-box 生成守护进程文件 # Sing-box 生成守护进程文件
sing-box_systemd() { sing-box_systemd() {
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] SING_BOX_SERVICE="[Unit]
Description=sing-box service Description=sing-box service
Documentation=https://sing-box.sagernet.org Documentation=https://sing-box.sagernet.org
@@ -1820,7 +1943,7 @@ 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 ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure Restart=on-failure
RestartSec=10 RestartSec=10
@@ -1830,10 +1953,47 @@ LimitNOFILE=infinity
WantedBy=multi-user.target" 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 生成守护进程文件
argo_systemd() { argo_systemd() {
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 cat > /etc/systemd/system/argo.service << EOF
[Unit] [Unit]
Description=Cloudflare Tunnel Description=Cloudflare Tunnel
@@ -1841,20 +2001,23 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
WorkingDirectory=$WORK_DIR
NoNewPrivileges=yes NoNewPrivileges=yes
TimeoutStartSec=0 TimeoutStartSec=0
ExecStart=$ARGO_RUNS ExecStart=${ARGO_RUNS}
Restart=on-failure Restart=on-failure
RestartSec=5s RestartSec=5s
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
systemctl daemon-reload
fi
} }
# 获取原有各协议的参数,先清空所有的 key-value # 获取原有各协议的参数,先清空所有的 key-value
fetch_nodes_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}}') 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) [[ -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 # 如有 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 端口和路径 # 获取 Nginx 端口和路径
[[ "${IS_SUB}" = 'is_sub' || "${IS_ARGO}" = 'is_argo' ]] && local NGINX_JSON=$(cat ${WORK_DIR}/nginx.conf) && [[ "${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 unset CLOUDFLARED_PID METRICS_ADDRESS ARGO_DOMAIN
local QUICKTUNNEL_ERROR_TIME=20 local QUICKTUNNEL_ERROR_TIME=20
until [ -n "$ARGO_DOMAIN" ]; do 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}') [ "$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]+$ ]] && METRICS_ADDRESS=$(ss -nltp | grep "pid=$CLOUDFLARED_PID" | awk '{print $4}') [[ -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}') [ -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 [[ ! "$ARGO_DOMAIN" =~ trycloudflare\.com$ ]] && (( QUICKTUNNEL_ERROR_TIME-- )) && sleep 2 || break
[ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) " [ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) "
@@ -1948,23 +2119,40 @@ install_sing-box() {
# 生成 Nginx 配置文件 # 生成 Nginx 配置文件
[ -n "$PORT_NGINX" ] && export_nginx_conf_file [ -n "$PORT_NGINX" ] && export_nginx_conf_file
# 如果 Alpine 系统,放到开机自启动 # Alpine 系统启动 sing-box 服务
if [ "$SYSTEM" = 'Alpine' ]; then [ "$SYSTEM" != 'Alpine' ] && cmd_systemctl daemon-reload
cat > /etc/local.d/sing-box.start << EOF cmd_systemctl enable sing-box
#!/usr/bin/env bash
systemctl start sing-box # 等待服务启动
EOF sleep 2
chmod +x /etc/local.d/sing-box.start
rc-update add local >/dev/null 2>&1 # 检查服务是否成功启动
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 fi
# 等待所有后台进程完成后,再次检测状态,运行 Sing-box # 如果配置了 Argo,也启动 Argo 服务
check_install
sleep 1
check_sing-box_status
if [ "$IS_ARGO" = 'is_argo' ]; then 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 fi
} }
@@ -1973,15 +2161,6 @@ export_list() {
check_install 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 [ "$IS_INSTALL" != 'install' ] && fetch_nodes_value
# IPv6 时的 IP 处理 # IPv6 时的 IP 处理
@@ -2829,7 +3008,7 @@ change_protocols() {
fi fi
# 获取 ws 的 argo 或者 origin 状态 # 获取 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 local ARGO_ORIGIN_RULES_STATUS=is_argo
ARGO_RUNS=$(sed -n "s/^ExecStart=\(.*\)/\1/gp" /etc/systemd/system/argo.service) 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 elif ls ${WORK_DIR}/conf/*-ws*inbounds.json >/dev/null 2>&1; then
@@ -2953,7 +3132,7 @@ change_protocols() {
argo_systemd argo_systemd
cmd_systemctl enable argo >/dev/null 2>&1 cmd_systemctl enable argo >/dev/null 2>&1
fi 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 cmd_systemctl disable argo >/dev/null 2>&1
rm -f /etc/systemd/system/argo.service rm -f /etc/systemd/system/argo.service
[ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.* [ -s ${WORK_DIR}/tunnel.json ] && rm -f ${WORK_DIR}/tunnel.*
@@ -2965,22 +3144,36 @@ change_protocols() {
# 运行 sing-box # 运行 sing-box
cmd_systemctl enable sing-box cmd_systemctl enable sing-box
# 等待服务启动
sleep 3
# 再次检测状态,运行 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
check_sing-box_status # 导出节点和订阅服务信息
export_list export_list
} }
# 卸载 sing-box 全家桶 # 卸载 sing-box 全家桶
uninstall() { uninstall() {
if [ -d ${WORK_DIR} ]; then 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 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 else
cmd_systemctl disable sing-box 2>/dev/null cmd_systemctl disable sing-box &>/dev/null
fi fi
sleep 1 sleep 1
[[ -s ${WORK_DIR}/nginx.conf && $(ps -ef | grep 'nginx' | wc -l) -le 1 ]] && reading "\n $(text 83) " REMOVE_NGINX [[ -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 else
error "\n $(text 15) \n" error "\n $(text 15) \n"
fi 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 的最新版本 # Sing-box 的最新版本
@@ -3022,8 +3208,34 @@ version() {
if [ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ]; then if [ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ]; then
cmd_systemctl disable sing-box 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 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 else
error "\n $(text 42) " error "\n $(text 42) "
fi fi
@@ -3072,8 +3284,60 @@ menu_setting() {
OPTION[12]="12. $(text 76)" OPTION[12]="12. $(text 76)"
ACTION[1]() { export_list; exit 0; } 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[4]() { change_argo; exit; }
ACTION[5]() { change_start_port; exit; } ACTION[5]() { change_start_port; exit; }
ACTION[6]() { version; exit; } ACTION[6]() { version; exit; }
@@ -3165,10 +3429,15 @@ for z in ${!ALL_PARAMETER[@]}; do
error "\n Sing-box $(text 26) " error "\n Sing-box $(text 26) "
elif [ "${STATUS[0]}" = "$(text 28)" ]; then elif [ "${STATUS[0]}" = "$(text 28)" ]; then
cmd_systemctl disable sing-box 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 elif [ "${STATUS[0]}" = "$(text 27)" ]; then
cmd_systemctl enable sing-box 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 fi
exit 0 exit 0
;; ;;
@@ -3178,15 +3447,26 @@ for z in ${!ALL_PARAMETER[@]}; do
error "\n Argo $(text 26) " error "\n Argo $(text 26) "
elif [ "${STATUS[1]}" = "$(text 28)" ]; then elif [ "${STATUS[1]}" = "$(text 28)" ]; then
cmd_systemctl disable argo cmd_systemctl disable argo
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)" [[ "$(systemctl is-active argo)" =~ 'inactive'|'unknown' ]] && info "\n Argo $(text 27) $(text 37)"
fi
elif [ "${STATUS[1]}" = "$(text 27)" ]; then elif [ "${STATUS[1]}" = "$(text 27)" ]; then
cmd_systemctl enable argo cmd_systemctl enable argo
sleep 2 sleep 2
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 if [ "$(systemctl is-active argo)" = 'active' ]; then
info "\n Argo $(text 28) $(text 37)" info "\n Argo $(text 28) $(text 37)"
grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list grep -q '\--url' /etc/systemd/system/argo.service && fetch_quicktunnel_domain && export_list
fi fi
fi fi
fi
exit 0 exit 0
;; ;;
-T ) -T )