From 660e0574ef20a4823a6e9d4026a5d4ac31b88298 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Tue, 12 May 2026 15:37:12 +0800 Subject: [PATCH] feat: add -debug flag with file logging to fscan_debug.log --- common/flag.go | 6 ++++++ common/flag_config.go | 1 + common/i18n/locales/en.yaml | 2 ++ common/i18n/locales/zh.yaml | 2 ++ common/logger.go | 10 ++++++++++ common/logging/logger.go | 39 ++++++++++++++++++++++++++++++++++++- main.go | 1 + 7 files changed, 60 insertions(+), 1 deletion(-) diff --git a/common/flag.go b/common/flag.go index 94406fc..00ccabe 100644 --- a/common/flag.go +++ b/common/flag.go @@ -182,6 +182,7 @@ func Flag(Info *HostInfo) error { flag.BoolVar(&fv.Silent, "silent", false, i18n.GetText("flag_silent_mode")) flag.BoolVar(&fv.NoColor, "nocolor", false, i18n.GetText("flag_no_color")) flag.StringVar(&fv.LogLevel, "log", LogLevelBaseInfoSuccess, i18n.GetText("flag_log_level")) + flag.BoolVar(&fv.Debug, "debug", false, i18n.GetText("flag_debug")) flag.BoolVar(&fv.DisableProgress, "nopg", false, i18n.GetText("flag_disable_progress")) flag.BoolVar(&fv.PerfStats, "perf", false, "输出性能统计JSON") @@ -285,6 +286,11 @@ func shouldShowHelp(Info *HostInfo, fv *FlagVars) bool { func checkParameterConflicts() error { fv := flagVars + // -debug 等价于 -log debug + if fv.Debug { + fv.LogLevel = LogLevelDebug + } + // 检查 -ao 和 -m icmp 同时指定的情况(向后兼容提示) if fv.AliveOnly && fv.ScanMode == "icmp" { LogInfo(i18n.GetText("param_conflict_ao_icmp_both")) diff --git a/common/flag_config.go b/common/flag_config.go index b4326c6..cca579b 100644 --- a/common/flag_config.go +++ b/common/flag_config.go @@ -95,6 +95,7 @@ type FlagVars struct { Silent bool NoColor bool LogLevel string + Debug bool DisableProgress bool PerfStats bool Language string diff --git a/common/i18n/locales/en.yaml b/common/i18n/locales/en.yaml index d506fcc..9d7c58c 100644 --- a/common/i18n/locales/en.yaml +++ b/common/i18n/locales/en.yaml @@ -30,6 +30,8 @@ flag_disable_ping: other: "Disable ping detection" flag_disable_tcp_probe: other: "Disable TCP supplementary probe" +flag_debug: + other: "Enable debug mode, write logs to fscan_debug.log" flag_alive_only: other: "Alive detection only" flag_username: diff --git a/common/i18n/locales/zh.yaml b/common/i18n/locales/zh.yaml index 0941474..dfa506f 100644 --- a/common/i18n/locales/zh.yaml +++ b/common/i18n/locales/zh.yaml @@ -30,6 +30,8 @@ flag_disable_ping: other: "禁用ping探测" flag_disable_tcp_probe: other: "禁用TCP补充探测" +flag_debug: + other: "开启调试模式,日志写入fscan_debug.log" flag_alive_only: other: "仅进行存活探测" flag_username: diff --git a/common/logger.go b/common/logger.go index 7f8568d..323a013 100644 --- a/common/logger.go +++ b/common/logger.go @@ -30,6 +30,9 @@ func getGlobalLogger() *logging.Logger { Silent: fv.Silent, StartTime: GetGlobalState().GetStartTime(), } + if fv.Debug { + config.DebugLogFile = "fscan_debug.log" + } globalLogger = logging.NewLogger(config) globalLogger.SetCoordinatedOutput(LogWithProgress) }) @@ -78,3 +81,10 @@ func LogVuln(result string) { getGlobalLogger().Vuln(result) } // LogError 输出错误日志 func LogError(errMsg string) { getGlobalLogger().Error(errMsg) } + +// CloseLogger 关闭日志系统,释放文件资源 +func CloseLogger() { + if globalLogger != nil { + globalLogger.Close() + } +} diff --git a/common/logging/logger.go b/common/logging/logger.go index 24611ed..4fe190c 100644 --- a/common/logging/logger.go +++ b/common/logging/logger.go @@ -2,6 +2,7 @@ package logging import ( "fmt" + "os" "strings" "sync" "time" @@ -27,6 +28,7 @@ type LoggerConfig struct { Silent bool `json:"silent"` StartTime time.Time `json:"start_time"` LevelColors map[LogLevel]interface{} `json:"-"` + DebugLogFile string `json:"debug_log_file"` } // DefaultLoggerConfig 默认日志器配置 @@ -48,6 +50,7 @@ type Logger struct { startTime time.Time coordinatedOutput func(string) initialized bool + debugFile *os.File } // NewLogger 创建新的日志管理器 @@ -56,11 +59,20 @@ func NewLogger(config *LoggerConfig) *Logger { config = DefaultLoggerConfig() } - return &Logger{ + l := &Logger{ config: config, startTime: config.StartTime, initialized: true, } + + if config.DebugLogFile != "" { + f, err := os.OpenFile(config.DebugLogFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) + if err == nil { + l.debugFile = f + } + } + + return l } // Initialize 初始化日志器 @@ -139,12 +151,37 @@ func (l *Logger) log(level LogLevel, content string) { l.outputMessage(level, logMsg) } + // 写入debug日志文件(纯文本,无颜色) + if l.debugFile != nil { + timestamp := time.Since(l.startTime).Truncate(time.Millisecond) + if strings.Contains(content, "\n") { + lines := strings.Split(content, "\n") + for _, line := range lines { + if line != "" { + fmt.Fprintf(l.debugFile, "[%s] %s %s\n", timestamp, prefix, line) + } + } + } else { + fmt.Fprintf(l.debugFile, "[%s] %s %s\n", timestamp, prefix, content) + } + } + // 根据慢速输出设置决定是否添加延迟 if l.config.SlowOutput { time.Sleep(SlowOutputDelay) } } +// Close 关闭日志器,释放文件资源 +func (l *Logger) Close() { + l.mu.Lock() + defer l.mu.Unlock() + if l.debugFile != nil { + _ = l.debugFile.Close() + l.debugFile = nil + } +} + // shouldLog 检查是否应该记录该级别的日志 // 层级过滤:消息级别 >= 配置级别 时显示,Error 始终显示 func (l *Logger) shouldLog(level LogLevel) bool { diff --git a/main.go b/main.go index 9c598c1..125e582 100644 --- a/main.go +++ b/main.go @@ -65,6 +65,7 @@ func main() { os.Exit(130) // 128 + SIGINT(2) = 130,标准的中断退出码 }() defer func() { _ = common.Cleanup() }() + defer common.CloseLogger() // 执行扫描 core.RunScan(context.Background(), *result.Info, result.Session)