From 062f2bd7146d6c441558a7b761f5bb53b4f3ce89 Mon Sep 17 00:00:00 2001 From: Sora39831 <540587985@qq.com> Date: Sun, 5 Apr 2026 03:12:29 +0800 Subject: [PATCH] fix migrate panic and include release workflow updates --- .github/workflows/release.yml | 103 ++++++++++++++++++++++++---------- logger/logger.go | 22 ++++++++ main.go | 14 +++++ 3 files changed, 109 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 77553f9c..e64b5180 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,6 +91,15 @@ jobs: go-version-file: go.mod check-latest: true + - name: Cache Go build + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + key: gobuild-${{ matrix.platform }}-${{ hashFiles('**/*.go', 'go.mod', 'go.sum') }} + restore-keys: | + gobuild-${{ matrix.platform }}- + - name: Get latest Xray version id: xray_version run: | @@ -98,6 +107,66 @@ jobs: echo "version=$LATEST" >> "$GITHUB_OUTPUT" echo "Latest Xray version: $LATEST" + - name: Cache Xray binary + id: cache_xray + uses: actions/cache@v4 + with: + path: /tmp/xray + key: xray-${{ matrix.platform }}-${{ steps.xray_version.outputs.version }} + restore-keys: | + xray-${{ matrix.platform }}- + + - name: Download Xray + if: steps.cache_xray.outputs.cache-hit != 'true' + run: | + Xray_URL="https://github.com/XTLS/Xray-core/releases/download/${{ steps.xray_version.outputs.version }}/" + declare -A XRAY_MAP=( + [amd64]="Xray-linux-64.zip" + [arm64]="Xray-linux-arm64-v8a.zip" + [armv7]="Xray-linux-arm32-v7a.zip" + [armv6]="Xray-linux-arm32-v6.zip" + [386]="Xray-linux-32.zip" + [armv5]="Xray-linux-arm32-v5.zip" + [s390x]="Xray-linux-s390x.zip" + ) + XRAY_FILE="${XRAY_MAP[${{ matrix.platform }}]}" + [ -z "$XRAY_FILE" ] && { echo "Unknown platform: ${{ matrix.platform }}" >&2; exit 1; } + mkdir -p /tmp/xray + curl -fL -sS --retry 3 --retry-delay 5 -o "/tmp/xray/$XRAY_FILE" "${Xray_URL}${XRAY_FILE}" + cd /tmp/xray + unzip -q "$XRAY_FILE" + rm -f "$XRAY_FILE" + + - name: Get cache date + id: cache_date + run: echo "date=$(date -u +%Y-%m-%d)" >> "$GITHUB_OUTPUT" + + - name: Cache geo data + id: cache_geo + uses: actions/cache@v4 + with: + path: /tmp/geo + key: geo-${{ steps.cache_date.outputs.date }} + + - name: Download geo data + if: steps.cache_geo.outputs.cache-hit != 'true' + run: | + mkdir -p /tmp/geo + cd /tmp/geo + curl -fL -sS --retry 3 -o geoip.dat \ + https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat & + curl -fL -sS --retry 3 -o geosite.dat \ + https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat & + curl -fL -sS --retry 3 -o geoip_IR.dat \ + https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat & + curl -fL -sS --retry 3 -o geosite_IR.dat \ + https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat & + curl -fL -sS --retry 3 -o geoip_RU.dat \ + https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat & + curl -fL -sS --retry 3 -o geosite_RU.dat \ + https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat & + wait + - name: Cache Bootlin toolchain uses: actions/cache@v4 with: @@ -157,37 +226,11 @@ jobs: mkdir x-ui/bin cd x-ui/bin - # Download Xray - Xray_URL="https://github.com/XTLS/Xray-core/releases/download/${{ steps.xray_version.outputs.version }}/" - declare -A XRAY_MAP=( - [amd64]="Xray-linux-64.zip" - [arm64]="Xray-linux-arm64-v8a.zip" - [armv7]="Xray-linux-arm32-v7a.zip" - [armv6]="Xray-linux-arm32-v6.zip" - [386]="Xray-linux-32.zip" - [armv5]="Xray-linux-arm32-v5.zip" - [s390x]="Xray-linux-s390x.zip" - ) - XRAY_FILE="${XRAY_MAP[${{ matrix.platform }}]}" - [ -z "$XRAY_FILE" ] && { echo "Unknown platform: ${{ matrix.platform }}" >&2; exit 1; } - curl -fL -sS --retry 3 --retry-delay 5 -o "$XRAY_FILE" "${Xray_URL}${XRAY_FILE}" - unzip -q "$XRAY_FILE" - rm -f "$XRAY_FILE" + # Copy Xray from cache + cp /tmp/xray/xray . - # Download geo data in parallel - curl -fL -sS --retry 3 -o geoip.dat \ - https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat & - curl -fL -sS --retry 3 -o geosite.dat \ - https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat & - curl -fL -sS --retry 3 -o geoip_IR.dat \ - https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat & - curl -fL -sS --retry 3 -o geosite_IR.dat \ - https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat & - curl -fL -sS --retry 3 -o geoip_RU.dat \ - https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat & - curl -fL -sS --retry 3 -o geosite_RU.dat \ - https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat & - wait + # Copy geo data from cache + cp /tmp/geo/* . mv xray xray-linux-${{ matrix.platform }} cd ../.. diff --git a/logger/logger.go b/logger/logger.go index 7d26dcd0..c322d70b 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "runtime" + "sync" "time" "github.com/mhsanaei/3x-ui/v2/config" @@ -22,6 +23,7 @@ const ( var ( logger *logging.Logger logFile *os.File + once sync.Once // logBuffer maintains recent log entries in memory for web UI retrieval logBuffer []struct { @@ -31,6 +33,16 @@ var ( } ) +// ensureLogger lazily initializes logger to avoid nil-pointer panics +// when code paths log before explicit InitLogger() call. +func ensureLogger() { + once.Do(func() { + if logger == nil { + InitLogger(logging.INFO) + } + }) +} + // InitLogger initializes dual logging backends: console/syslog and file. // Console logging uses the specified level, file logging always uses DEBUG level. func InitLogger(level logging.Level) { @@ -127,60 +139,70 @@ func CloseLogger() { // Debug logs a debug message and adds it to the log buffer. func Debug(args ...any) { + ensureLogger() logger.Debug(args...) addToBuffer("DEBUG", fmt.Sprint(args...)) } // Debugf logs a formatted debug message and adds it to the log buffer. func Debugf(format string, args ...any) { + ensureLogger() logger.Debugf(format, args...) addToBuffer("DEBUG", fmt.Sprintf(format, args...)) } // Info logs an info message and adds it to the log buffer. func Info(args ...any) { + ensureLogger() logger.Info(args...) addToBuffer("INFO", fmt.Sprint(args...)) } // Infof logs a formatted info message and adds it to the log buffer. func Infof(format string, args ...any) { + ensureLogger() logger.Infof(format, args...) addToBuffer("INFO", fmt.Sprintf(format, args...)) } // Notice logs a notice message and adds it to the log buffer. func Notice(args ...any) { + ensureLogger() logger.Notice(args...) addToBuffer("NOTICE", fmt.Sprint(args...)) } // Noticef logs a formatted notice message and adds it to the log buffer. func Noticef(format string, args ...any) { + ensureLogger() logger.Noticef(format, args...) addToBuffer("NOTICE", fmt.Sprintf(format, args...)) } // Warning logs a warning message and adds it to the log buffer. func Warning(args ...any) { + ensureLogger() logger.Warning(args...) addToBuffer("WARNING", fmt.Sprint(args...)) } // Warningf logs a formatted warning message and adds it to the log buffer. func Warningf(format string, args ...any) { + ensureLogger() logger.Warningf(format, args...) addToBuffer("WARNING", fmt.Sprintf(format, args...)) } // Error logs an error message and adds it to the log buffer. func Error(args ...any) { + ensureLogger() logger.Error(args...) addToBuffer("ERROR", fmt.Sprint(args...)) } // Errorf logs a formatted error message and adds it to the log buffer. func Errorf(format string, args ...any) { + ensureLogger() logger.Errorf(format, args...) addToBuffer("ERROR", fmt.Sprintf(format, args...)) } diff --git a/main.go b/main.go index 3ba5602b..329c5130 100644 --- a/main.go +++ b/main.go @@ -391,6 +391,20 @@ func GetListenIP(getListen bool) { // migrateDb performs database migration operations for the 3x-ui panel. func migrateDb() { inboundService := service.InboundService{} + switch config.GetLogLevel() { + case config.Debug: + logger.InitLogger(logging.DEBUG) + case config.Info: + logger.InitLogger(logging.INFO) + case config.Notice: + logger.InitLogger(logging.NOTICE) + case config.Warning: + logger.InitLogger(logging.WARNING) + case config.Error: + logger.InitLogger(logging.ERROR) + default: + logger.InitLogger(logging.INFO) + } err := database.InitDB() if err != nil {