mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-07-13 21:02:44 +08:00
perf: 优化进度条
This commit is contained in:
parent
ceede3cd68
commit
a603e13d3b
@ -119,6 +119,7 @@ var (
|
|||||||
NoColor bool // 禁用彩色输出
|
NoColor bool // 禁用彩色输出
|
||||||
JsonFormat bool // JSON格式输出
|
JsonFormat bool // JSON格式输出
|
||||||
LogLevel string // 日志输出级别
|
LogLevel string // 日志输出级别
|
||||||
|
NoProgress bool // 禁用进度条显示
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
139
Common/Flag.go
139
Common/Flag.go
@ -2,18 +2,138 @@ package Common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Banner() {
|
func Banner() {
|
||||||
banner := `
|
// 定义暗绿色系
|
||||||
___ _
|
colors := []color.Attribute{
|
||||||
/ _ \ ___ ___ _ __ __ _ ___| | __
|
color.FgGreen, // 基础绿
|
||||||
/ /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ /
|
color.FgHiGreen, // 亮绿
|
||||||
/ /_\\_____\__ \ (__| | | (_| | (__| <
|
}
|
||||||
\____/ |___/\___|_| \__,_|\___|_|\_\
|
|
||||||
fscan version: ` + version + `
|
lines := []string{
|
||||||
`
|
" ___ _ ",
|
||||||
print(banner)
|
" / _ \\ ___ ___ _ __ __ _ ___| | __ ",
|
||||||
|
" / /_\\/____/ __|/ __| '__/ _` |/ __| |/ /",
|
||||||
|
"/ /_\\\\_____\\__ \\ (__| | | (_| | (__| < ",
|
||||||
|
"\\____/ |___/\\___|_| \\__,_|\\___|_|\\_\\ ",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取最长行的长度
|
||||||
|
maxLength := 0
|
||||||
|
for _, line := range lines {
|
||||||
|
if len(line) > maxLength {
|
||||||
|
maxLength = len(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清屏并隐藏光标
|
||||||
|
fmt.Print("\033[H\033[2J\033[?25l")
|
||||||
|
defer fmt.Print("\033[?25h")
|
||||||
|
|
||||||
|
// 创建边框
|
||||||
|
topBorder := "┌" + strings.Repeat("─", maxLength+2) + "┐"
|
||||||
|
bottomBorder := "└" + strings.Repeat("─", maxLength+2) + "┘"
|
||||||
|
|
||||||
|
// 呼吸灯效果循环
|
||||||
|
for cycle := 0; cycle < 2; cycle++ { // 2个完整循环
|
||||||
|
// 亮度由暗到亮
|
||||||
|
for i := 0; i <= 10; i++ {
|
||||||
|
fmt.Print("\033[H")
|
||||||
|
dim := float64(i) / 10.0
|
||||||
|
|
||||||
|
printDimmed(topBorder, colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for lineNum, line := range lines {
|
||||||
|
printDimmed("│ ", colors[0], dim)
|
||||||
|
for _, char := range line {
|
||||||
|
printDimmed(string(char), colors[lineNum%2], dim)
|
||||||
|
}
|
||||||
|
padding := maxLength - len(line)
|
||||||
|
printDimmed(strings.Repeat(" ", padding)+" │", colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
printDimmed(bottomBorder, colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
vStr := fmt.Sprintf(" Fscan Version: %s", version)
|
||||||
|
printDimmed(vStr, colors[1], dim)
|
||||||
|
fmt.Print("\n\n")
|
||||||
|
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 亮度由亮到暗
|
||||||
|
for i := 10; i >= 0; i-- {
|
||||||
|
fmt.Print("\033[H")
|
||||||
|
dim := float64(i) / 10.0
|
||||||
|
|
||||||
|
printDimmed(topBorder, colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for lineNum, line := range lines {
|
||||||
|
printDimmed("│ ", colors[0], dim)
|
||||||
|
for _, char := range line {
|
||||||
|
printDimmed(string(char), colors[lineNum%2], dim)
|
||||||
|
}
|
||||||
|
padding := maxLength - len(line)
|
||||||
|
printDimmed(strings.Repeat(" ", padding)+" │", colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
printDimmed(bottomBorder, colors[0], dim)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
vStr := fmt.Sprintf(" Fscan Version: %s", version)
|
||||||
|
printDimmed(vStr, colors[1], dim)
|
||||||
|
fmt.Print("\n\n")
|
||||||
|
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后显示完整亮度的版本
|
||||||
|
fmt.Print("\033[H")
|
||||||
|
printDimmed(topBorder, colors[0], 1.0)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
for lineNum, line := range lines {
|
||||||
|
printDimmed("│ ", colors[0], 1.0)
|
||||||
|
for _, char := range line {
|
||||||
|
printDimmed(string(char), colors[lineNum%2], 1.0)
|
||||||
|
}
|
||||||
|
padding := maxLength - len(line)
|
||||||
|
printDimmed(strings.Repeat(" ", padding)+" │", colors[0], 1.0)
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
printDimmed(bottomBorder, colors[0], 1.0)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
vStr := fmt.Sprintf(" Fscan Version: %s", version)
|
||||||
|
printDimmed(vStr, colors[1], 1.0)
|
||||||
|
fmt.Print("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:打印带透明度的文字
|
||||||
|
func printDimmed(text string, col color.Attribute, dim float64) {
|
||||||
|
if dim < 0.2 {
|
||||||
|
fmt.Print(strings.Repeat(" ", len(text)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
intensity := int(255 * dim)
|
||||||
|
fmt.Printf("\033[38;2;%d;%d;%dm%s\033[0m",
|
||||||
|
int(float64(0)*dim),
|
||||||
|
intensity,
|
||||||
|
int(float64(0)*dim),
|
||||||
|
text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flag(Info *HostInfo) {
|
func Flag(Info *HostInfo) {
|
||||||
@ -128,6 +248,7 @@ func Flag(Info *HostInfo) {
|
|||||||
flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示")
|
flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示")
|
||||||
flag.BoolVar(&JsonFormat, "json", false, "以JSON格式输出结果")
|
flag.BoolVar(&JsonFormat, "json", false, "以JSON格式输出结果")
|
||||||
flag.StringVar(&LogLevel, "log", LogLevelInfo, "日志输出级别(ALL/SUCCESS/ERROR/INFO/DEBUG)")
|
flag.StringVar(&LogLevel, "log", LogLevelInfo, "日志输出级别(ALL/SUCCESS/ERROR/INFO/DEBUG)")
|
||||||
|
flag.BoolVar(&NoProgress, "noprogress", false, "禁用进度条显示")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@ func formatLogMessage(entry *LogEntry) string {
|
|||||||
return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content)
|
return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改 printLog 函数
|
||||||
func printLog(entry *LogEntry) {
|
func printLog(entry *LogEntry) {
|
||||||
// 先检查日志级别
|
|
||||||
if LogLevel != LogLevelAll &&
|
if LogLevel != LogLevelAll &&
|
||||||
entry.Level != LogLevel &&
|
entry.Level != LogLevel &&
|
||||||
!(LogLevel == LogLevelInfo && (entry.Level == LogLevelInfo || entry.Level == LogLevelSuccess)) {
|
!(LogLevel == LogLevelInfo && (entry.Level == LogLevelInfo || entry.Level == LogLevelSuccess)) {
|
||||||
@ -92,11 +92,15 @@ func printLog(entry *LogEntry) {
|
|||||||
OutputMutex.Lock()
|
OutputMutex.Lock()
|
||||||
defer OutputMutex.Unlock()
|
defer OutputMutex.Unlock()
|
||||||
|
|
||||||
|
// 确保清除当前进度条
|
||||||
|
if ProgressBar != nil {
|
||||||
|
ProgressBar.Clear()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印日志
|
||||||
logMsg := formatLogMessage(entry)
|
logMsg := formatLogMessage(entry)
|
||||||
// 只在输出到终端时处理进度条
|
|
||||||
if !NoColor {
|
if !NoColor {
|
||||||
// 清除当前行
|
|
||||||
fmt.Print("\033[2K\r")
|
|
||||||
if colorAttr, ok := logColors[entry.Level]; ok {
|
if colorAttr, ok := logColors[entry.Level]; ok {
|
||||||
color.New(colorAttr).Println(logMsg)
|
color.New(colorAttr).Println(logMsg)
|
||||||
} else {
|
} else {
|
||||||
@ -105,6 +109,14 @@ func printLog(entry *LogEntry) {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Println(logMsg)
|
fmt.Println(logMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保日志完全输出
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
|
// 重新渲染进度条
|
||||||
|
if ProgressBar != nil {
|
||||||
|
ProgressBar.RenderBlank()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogError(errMsg string) {
|
func LogError(errMsg string) {
|
||||||
|
111
Core/Scanner.go
111
Core/Scanner.go
@ -119,6 +119,15 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
|
|||||||
loadedPlugins := make([]string, 0)
|
loadedPlugins := make([]string, 0)
|
||||||
// 先遍历一遍计算实际要执行的任务数
|
// 先遍历一遍计算实际要执行的任务数
|
||||||
actualTasks := 0
|
actualTasks := 0
|
||||||
|
|
||||||
|
// 定义任务结构
|
||||||
|
type ScanTask struct {
|
||||||
|
pluginName string
|
||||||
|
target Common.HostInfo
|
||||||
|
}
|
||||||
|
tasks := make([]ScanTask, 0)
|
||||||
|
|
||||||
|
// 第一次遍历:计算任务数和收集要执行的插件
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
targetPort, _ := strconv.Atoi(target.Ports)
|
targetPort, _ := strconv.Atoi(target.Ports)
|
||||||
|
|
||||||
@ -131,80 +140,41 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
|
|||||||
if Common.LocalScan {
|
if Common.LocalScan {
|
||||||
if len(plugin.Ports) == 0 {
|
if len(plugin.Ports) == 0 {
|
||||||
actualTasks++
|
actualTasks++
|
||||||
|
loadedPlugins = append(loadedPlugins, pluginName)
|
||||||
|
tasks = append(tasks, ScanTask{
|
||||||
|
pluginName: pluginName,
|
||||||
|
target: target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSinglePlugin {
|
if isSinglePlugin {
|
||||||
actualTasks++
|
actualTasks++
|
||||||
|
loadedPlugins = append(loadedPlugins, pluginName)
|
||||||
|
tasks = append(tasks, ScanTask{
|
||||||
|
pluginName: pluginName,
|
||||||
|
target: target,
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(plugin.Ports) > 0 {
|
if len(plugin.Ports) > 0 {
|
||||||
if plugin.HasPort(targetPort) {
|
if plugin.HasPort(targetPort) {
|
||||||
actualTasks++
|
actualTasks++
|
||||||
|
loadedPlugins = append(loadedPlugins, pluginName)
|
||||||
|
tasks = append(tasks, ScanTask{
|
||||||
|
pluginName: pluginName,
|
||||||
|
target: target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actualTasks++
|
actualTasks++
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化进度条
|
|
||||||
Common.ProgressBar = progressbar.NewOptions(actualTasks,
|
|
||||||
progressbar.OptionEnableColorCodes(true),
|
|
||||||
progressbar.OptionShowCount(),
|
|
||||||
progressbar.OptionSetWidth(15),
|
|
||||||
progressbar.OptionSetDescription("[cyan]扫描进度:[reset]"),
|
|
||||||
progressbar.OptionSetTheme(progressbar.Theme{
|
|
||||||
Saucer: "[green]=[reset]",
|
|
||||||
SaucerHead: "[green]>[reset]",
|
|
||||||
SaucerPadding: " ",
|
|
||||||
BarStart: "[",
|
|
||||||
BarEnd: "]",
|
|
||||||
}),
|
|
||||||
progressbar.OptionUseANSICodes(true),
|
|
||||||
progressbar.OptionSetRenderBlankState(true),
|
|
||||||
// 设置更新频率
|
|
||||||
progressbar.OptionThrottle(65*time.Millisecond),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 确保进度条首次渲染
|
|
||||||
Common.ProgressBar.RenderBlank()
|
|
||||||
time.Sleep(100 * time.Millisecond) // 给进度条一个短暂的初始化时间
|
|
||||||
|
|
||||||
for _, target := range targets {
|
|
||||||
targetPort, _ := strconv.Atoi(target.Ports)
|
|
||||||
|
|
||||||
for _, pluginName := range pluginsToRun {
|
|
||||||
plugin, exists := Common.PluginManager[pluginName]
|
|
||||||
if !exists {
|
|
||||||
Common.LogError(fmt.Sprintf("插件 %s 不存在", pluginName))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if Common.LocalScan {
|
|
||||||
if len(plugin.Ports) == 0 {
|
|
||||||
loadedPlugins = append(loadedPlugins, pluginName)
|
loadedPlugins = append(loadedPlugins, pluginName)
|
||||||
AddScan(pluginName, target, ch, wg)
|
tasks = append(tasks, ScanTask{
|
||||||
}
|
pluginName: pluginName,
|
||||||
continue
|
target: target,
|
||||||
}
|
})
|
||||||
|
|
||||||
if isSinglePlugin {
|
|
||||||
loadedPlugins = append(loadedPlugins, pluginName)
|
|
||||||
AddScan(pluginName, target, ch, wg)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(plugin.Ports) > 0 {
|
|
||||||
if plugin.HasPort(targetPort) {
|
|
||||||
loadedPlugins = append(loadedPlugins, pluginName)
|
|
||||||
AddScan(pluginName, target, ch, wg)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadedPlugins = append(loadedPlugins, pluginName)
|
|
||||||
AddScan(pluginName, target, ch, wg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,6 +192,31 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
|
|||||||
sort.Strings(finalPlugins)
|
sort.Strings(finalPlugins)
|
||||||
|
|
||||||
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", ")))
|
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", ")))
|
||||||
|
|
||||||
|
// 在初始化进度条的地方添加判断
|
||||||
|
if !Common.NoProgress {
|
||||||
|
Common.ProgressBar = progressbar.NewOptions(actualTasks,
|
||||||
|
progressbar.OptionEnableColorCodes(true),
|
||||||
|
progressbar.OptionShowCount(),
|
||||||
|
progressbar.OptionSetWidth(15),
|
||||||
|
progressbar.OptionSetDescription("[cyan]扫描进度:[reset]"),
|
||||||
|
progressbar.OptionSetTheme(progressbar.Theme{
|
||||||
|
Saucer: "[green]=[reset]",
|
||||||
|
SaucerHead: "[green]>[reset]",
|
||||||
|
SaucerPadding: " ",
|
||||||
|
BarStart: "[",
|
||||||
|
BarEnd: "]",
|
||||||
|
}),
|
||||||
|
progressbar.OptionThrottle(65*time.Millisecond),
|
||||||
|
progressbar.OptionUseANSICodes(true),
|
||||||
|
progressbar.OptionSetRenderBlankState(true),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始执行收集到的所有任务
|
||||||
|
for _, task := range tasks {
|
||||||
|
AddScan(task.pluginName, task.target, ch, wg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finishScan 完成扫描任务
|
// finishScan 完成扫描任务
|
||||||
|
Loading…
Reference in New Issue
Block a user