Files
SingboxForPanel/update.sh
2026-04-16 12:13:23 +08:00

142 lines
3.7 KiB
Bash

#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
BINARY_PATH="${BINARY_PATH:-/usr/local/bin/sing-box}"
RELEASE_BASE_URL="${RELEASE_BASE_URL:-https://s3.cloudyun.top/downloads/singbox}"
SERVICE_CANDIDATES=("${SERVICE_NAME:-}" "singbox" "sing-box")
echo -e "${GREEN}sing-box binary update script${NC}"
if [[ ${EUID} -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
OS="$(uname -s)"
if [[ "$OS" != "Linux" ]]; then
echo -e "${RED}This update script currently supports Linux only. Current OS: ${OS}${NC}"
exit 1
fi
ARCH="$(uname -m)"
case "$ARCH" in
x86_64) BINARY_ARCH="amd64" ;;
aarch64|arm64) BINARY_ARCH="arm64" ;;
armv7l|armv7) BINARY_ARCH="armv7" ;;
*)
echo -e "${RED}Unsupported architecture: ${ARCH}${NC}"
exit 1
;;
esac
DOWNLOAD_TARGET="${DOWNLOAD_TARGET:-linux-${BINARY_ARCH}}"
DOWNLOAD_URL="${DOWNLOAD_URL:-${RELEASE_BASE_URL}/sing-box-${DOWNLOAD_TARGET}}"
TMP_BINARY="$(mktemp)"
BACKUP_BINARY="$(mktemp)"
cleanup() {
rm -f "${TMP_BINARY}" "${BACKUP_BINARY}"
}
trap cleanup EXIT
detect_service_name() {
local candidate
for candidate in "${SERVICE_CANDIDATES[@]}"; do
if [[ -z "${candidate}" ]]; then
continue
fi
if systemctl list-unit-files --type=service --no-legend 2>/dev/null | awk '{print $1}' | grep -Fxq "${candidate}.service"; then
printf '%s\n' "${candidate}"
return 0
fi
done
return 1
}
download_binary() {
echo -e "${YELLOW}Downloading sing-box binary...${NC}"
echo -e "${YELLOW}Target: ${DOWNLOAD_TARGET}${NC}"
echo -e "${YELLOW}URL: ${DOWNLOAD_URL}${NC}"
if command -v curl >/dev/null 2>&1; then
curl -fL "${DOWNLOAD_URL}" -o "${TMP_BINARY}"
elif command -v wget >/dev/null 2>&1; then
wget -O "${TMP_BINARY}" "${DOWNLOAD_URL}"
else
echo -e "${RED}Neither curl nor wget is installed.${NC}"
exit 1
fi
chmod 0755 "${TMP_BINARY}"
}
validate_binary() {
if ! "${TMP_BINARY}" version >/dev/null 2>&1; then
echo -e "${RED}Downloaded file is not a valid sing-box binary.${NC}"
exit 1
fi
}
current_version() {
if [[ -x "${BINARY_PATH}" ]]; then
"${BINARY_PATH}" version 2>/dev/null | head -n 1 || true
fi
}
new_version() {
"${TMP_BINARY}" version 2>/dev/null | head -n 1 || true
}
rollback() {
echo -e "${RED}Update failed, rolling back to previous binary...${NC}"
install -m 0755 "${BACKUP_BINARY}" "${BINARY_PATH}"
if [[ -n "${SERVICE_NAME_DETECTED:-}" ]]; then
systemctl restart "${SERVICE_NAME_DETECTED}" || true
fi
}
download_binary
validate_binary
OLD_VERSION="$(current_version)"
NEW_VERSION="$(new_version)"
if [[ -n "${OLD_VERSION}" ]]; then
echo -e "${YELLOW}Current version: ${OLD_VERSION}${NC}"
else
echo -e "${YELLOW}Current version: not installed or unreadable${NC}"
fi
echo -e "${YELLOW}New version: ${NEW_VERSION}${NC}"
if [[ -x "${BINARY_PATH}" ]]; then
cp -f "${BINARY_PATH}" "${BACKUP_BINARY}"
else
: > "${BACKUP_BINARY}"
fi
install -m 0755 "${TMP_BINARY}" "${BINARY_PATH}"
SERVICE_NAME_DETECTED="$(detect_service_name || true)"
if [[ -n "${SERVICE_NAME_DETECTED}" ]]; then
echo -e "${YELLOW}Restarting service: ${SERVICE_NAME_DETECTED}${NC}"
if ! systemctl restart "${SERVICE_NAME_DETECTED}"; then
if [[ -s "${BACKUP_BINARY}" ]]; then
rollback
fi
exit 1
fi
echo -e "${GREEN}Service restarted successfully.${NC}"
else
echo -e "${YELLOW}No systemd service detected. Binary updated only.${NC}"
fi
echo -e "${GREEN}sing-box has been updated successfully.${NC}"
echo -e "${GREEN}Binary: ${BINARY_PATH}${NC}"
echo -e "${GREEN}Version: $(current_version)${NC}"