mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-31 18:24:10 +00:00
fix(xray): resolve relative log paths under panel log folder
Rewrite relative `log.access`/`log.error` values in the Xray config to absolute paths under config.GetLogFolder() so Xray writes log files alongside the panel's logs regardless of the panel's working directory. Absolute paths, empty/"none" values, and nested relative paths are left untouched.
This commit is contained in:
parent
f2f5d584b3
commit
7368359924
1 changed files with 54 additions and 0 deletions
|
|
@ -3,12 +3,15 @@ package service
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/database/model"
|
"github.com/mhsanaei/3x-ui/v3/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/logger"
|
"github.com/mhsanaei/3x-ui/v3/logger"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/util/json_util"
|
||||||
"github.com/mhsanaei/3x-ui/v3/xray"
|
"github.com/mhsanaei/3x-ui/v3/xray"
|
||||||
|
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
|
|
@ -104,6 +107,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
xrayConfig.LogConfig = resolveXrayLogPaths(xrayConfig.LogConfig)
|
||||||
|
|
||||||
_, _, _ = s.inboundService.AddTraffic(nil, nil)
|
_, _, _ = s.inboundService.AddTraffic(nil, nil)
|
||||||
|
|
||||||
|
|
@ -253,6 +257,56 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
||||||
return xrayConfig, nil
|
return xrayConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolveXrayLogPaths rewrites relative `log.access` / `log.error` values to
|
||||||
|
// absolute paths under config.GetLogFolder(), so Xray writes those files
|
||||||
|
// alongside the panel's other logs regardless of the working directory the
|
||||||
|
// panel was launched from. Values that are empty, "none", or already absolute
|
||||||
|
// are left untouched, as are unparseable log blocks.
|
||||||
|
func resolveXrayLogPaths(logCfg json_util.RawMessage) json_util.RawMessage {
|
||||||
|
if len(logCfg) == 0 {
|
||||||
|
return logCfg
|
||||||
|
}
|
||||||
|
var parsed map[string]any
|
||||||
|
if err := json.Unmarshal(logCfg, &parsed); err != nil {
|
||||||
|
return logCfg
|
||||||
|
}
|
||||||
|
changed := false
|
||||||
|
for _, key := range []string{"access", "error"} {
|
||||||
|
v, ok := parsed[key].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
trimmed := strings.TrimSpace(v)
|
||||||
|
if trimmed == "" || strings.EqualFold(trimmed, "none") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if filepath.IsAbs(trimmed) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cleaned := filepath.ToSlash(filepath.Clean(trimmed))
|
||||||
|
base := filepath.Base(cleaned)
|
||||||
|
if base == "" || base == "." || base == string(filepath.Separator) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Only rewrite bare names ("./access.log", "access.log").
|
||||||
|
// A nested relative path like "./logs/foo.log" is treated as
|
||||||
|
// a deliberate user choice and left alone.
|
||||||
|
if cleaned != base {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parsed[key] = filepath.Join(config.GetLogFolder(), base)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if !changed {
|
||||||
|
return logCfg
|
||||||
|
}
|
||||||
|
out, err := json.Marshal(parsed)
|
||||||
|
if err != nil {
|
||||||
|
return logCfg
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// healShadowsocksClientMethods is the same idea as applyShadowsocksClientMethod
|
// healShadowsocksClientMethods is the same idea as applyShadowsocksClientMethod
|
||||||
// (see client.go) but applied at xray-config-build time, to backfill the
|
// (see client.go) but applied at xray-config-build time, to backfill the
|
||||||
// per-client method field for legacy shadowsocks inbounds whose clients were
|
// per-client method field for legacy shadowsocks inbounds whose clients were
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue