ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

scan4all 中的彩色终端输出方案:fatih/color 库 API 全解与源码剖析

scan4all 中的彩色终端输出方案:fatih/color 库 API 全解与源码剖析 scan4all 中的彩色终端输出方案fatih/color 库 API 全解与源码剖析【免费下载链接】scan4allOfficial repository vuls Scan: 15000PoCs; 23 kinds of application password crack; 7000Web fingerprints; 146 protocols and 90000 rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all本文以 scan4all 仓库中内置vendor的依赖文档 vendor/github.com/fatih/color/README.md 为核心系统讲解 fatih/color 这个 Go ANSI 彩色输出库的安装方式、七类 API 用法标准颜色函数、组合复用、自定义 Writer、PrintFunc/FprintFunc、SprintFunc、全局 Set/Unset、启用/禁用控制并结合 color.go 源码剖析其 SGR 转义序列的生成机制、NoColor自动检测逻辑与对象缓存设计帮助读者在构建 CLI 安全工具时掌握一套完整、可复制的彩色输出实现方案。一、这个库是什么为什么 scan4all 依赖它fatih/color 让 Go 程序能够基于ANSI Escape CodesSGR 转义序列输出带颜色的终端文本并且对 Windows 终端提供支持。文档明确给出安装方式go get github.com/fatih/color在 scan4all 仓库中该库以 vendored 依赖形式存在go.mod 中声明了github.com/fatih/color v1.15.0 // indirect说明它是 scan4all 依赖图中被传递引入的库vendor 目录完整保留了其源码供编译与阅读vendor/github.com/fatih/color/color.go核心实现SGR 序列生成、全部打印 API、缓存机制vendor/github.com/fatih/color/color_windows.goWindows 平台适配vendor/github.com/fatih/color/doc.go包级文档vendor/github.com/fatih/color/LICENSE.mdMIT 协议值得一提的是scan4all 自身的扫描引擎另有一套独立实现pkg/kscan/lib/color/color.go 中通过colorMap/backgroundMap/formatMap三个字典将 red、bold 等字符串名映射到 ANSI 码如 red→31、background red→41、bold→1并定义了convANSI函数拼接\x1b[...m转义序列——这与 fatih/color 的sequence()方法思路一致可以视为对同一套 ANSI SGR 规范的两种落地。理解 fatih/color 的 API 后再阅读这套自研实现会非常顺畅。二、标准颜色辅助函数Standard colorsREADME 的第一类用法是包级快捷函数适合一次性打印// Print with default helper functions color.Cyan(Prints text in cyan.) // A newline will be appended automatically color.Blue(Prints %s in blue., text) // These are using the default foreground colors color.Red(We have red) color.Magenta(And many others ..)结合源码可以看出其底层机制Red、Cyan等包级函数最终都调用 colorPrintfunc colorPrint(format string, p Attribute, a ...interface{}) { c : getCachedColor(p) if !strings.HasSuffix(format, \n) { format \n // 自动补换行对应 README 中 A newline will be appended automatically } if len(a) 0 { c.Print(format) } else { c.Printf(format, a...) } }两个关键细节自动换行colorPrint会在 format 不以\n结尾时自动追加换行符这正是 README 示例中注释所描述的行为对象缓存getCachedColor通过全局colorsCache map[Attribute]*Color加sync.Mutex保护复用同一Attribute的 Color 对象避免频繁分配见 color.go 第 34 行、第 441-452 行。除 8 种标准前景色外源码还定义了高亮前景色FgHiBlack~FgHiWhite对应 90-97 码与高亮背景色BgHiBlack~BgHiWhite对应 100-107 码并提供了HiRed、HiGreenString等一整套高亮辅助函数color.go 第 80-114 行、第 544-616 行README 示例只展示了标准色部分。三、组合与复用颜色对象Mix and reuse colors第二类用法是创建可复用的*Color对象并链式Add属性// Create a new color object c : color.New(color.FgCyan).Add(color.Underline) c.Println(Prints cyan text with an underline.) // Or just add them to New() d : color.New(color.FgCyan, color.Bold) d.Printf(This prints bold cyan %s\n, too!.) // Mix up foreground and background colors, create new mixes! red : color.New(color.FgRed) boldRed : red.Add(color.Bold) boldRed.Println(This will print text in bold red.) whiteBackground : red.Add(color.BgWhite) whiteBackground.Println(Red text with white background.)从 New 函数 与 Add 函数 的实现可以确认语义type Color struct { params []Attribute noColor *bool } func (c *Color) Add(value ...Attribute) *Color { c.params append(c.params, value...) return c }params是一个[]Attribute切片Add把新属性追加进去并返回自身以支持链式调用。Attribute本质上就是 SGR 数字码type Attribute int基础格式 0-9Reset、Bold、Faint、Italic、Underline 等、前景色 30-37、高亮前景色 90-97、背景色 40-47、高亮背景色 100-107color.go 第 54-114 行。最终打印时sequence()方法把所有属性数字用分号连接嵌入\x1b[...m包裹文本func (c *Color) sequence() string { format : make([]string, len(c.params)) for i, v : range c.params { format[i] strconv.Itoa(int(v)) } return strings.Join(format, ;) } func (c *Color) format() string { return fmt.Sprintf(%s[%sm, escape, c.sequence()) }例如New(FgCyan).Add(Underline)打印时即产生\x1b[36;4m 文本 \x1b[0m。wrap方法第 373-379 行则用于 Sprint 系列先判断isNoColorSet()若禁用颜色直接返回原字符串否则返回format() s unformat()保证取回字符串与直接打印行为一致。四、使用自定义输出流io.Writer当输出目标不是标准输出时写入文件、日志 writer 等使用Fprint系列方法// Use your own io.Writer output color.New(color.FgBlue).Fprintln(myWriter, blue color!) blue : color.New(color.FgBlue) blue.Fprint(writer, This will print text in blue.)源码中 Fprint/Fprintf/Fprintln 的统一模式是先设置 SGR 序列defer复位func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { c.SetWriter(w) defer c.UnsetWriter(w) return fmt.Fprint(w, a...) }SetWriter/UnsetWriter是这一模式的底层原语第 169-190 行分别在w上写入转义序列与 Reset 序列。注意 Windows 用户的额外要求如果w是*os.File类型应先用colorable.NewColorable()包装源码注释中有此说明这是库对 Windows 支持的一部分。五、自定义打印函数PrintfFunc 与 PrintlnFunc第三、四类用法是把一个 Color 对象闭包化成自定义函数非常适合定义info/warn等语义化输出函数// Create a custom print function for convenience red : color.New(color.FgRed).PrintfFunc() red(Warning) red(Error: %s, err) // Mix up multiple attributes notice : color.New(color.Bold, color.FgGreen).PrintlnFunc() notice(Dont forget this...)FprintFunc/FprintfFunc/FprintlnFunc则把 writer 作为参数暴露出来blue : color.New(color.FgBlue).FprintfFunc() blue(myWriter, important notice: %s, stars) // Mix up with multiple attributes success : color.New(color.Bold, color.FgGreen).FprintlnFunc() success(myWriter, Dont forget this...)从 FprintFunc 等一组方法 看它们都只是返回一个包裹对应F*方法的匿名函数因此自定义函数与直接调用 Color 方法在行为上完全等价收益在于调用处更简洁。这种函数值模式在 CLI 工具中很常见——scan4all 的 pkg/kscan/core/slog/slog.go 就采用了类似的思路它定义Logger接口Println/Printf与内部logger结构体把modifier func(string) string作为每条日志的修饰函数info级别使用color.Green修饰、warn级别使用color.Red修饰第 49-68 行并配合log.Ldate|log.Ltime输出[]/[*]前缀的时间戳日志——这是将颜色修饰与日志框架解耦的一个可参考的工程实践。六、嵌入非彩色字符串SprintFunc 与 XXString 系列第五类用法是把带色片段作为普通字符串嵌入更长的输出中// Create SprintXxx functions to mix strings with other non-colorized strings: yellow : color.New(color.FgYellow).SprintFunc() red : color.New(color.FgRed).SprintFunc() fmt.Printf(This is a %s and this is %s.\n, yellow(warning), red(error)) info : color.New(color.FgWhite, color.BgGreen).SprintFunc() fmt.Printf(This %s rocks!\n, info(package)) // Use helper functions fmt.Println(This, color.RedString(warning), should be not neglected.) fmt.Printf(%v %v\n, color.GreenString(Info:), an important message.) // Windows supported too! Just dont forget to change the output to color.Output fmt.Fprintf(color.Output, Windows support: %s, color.GreenString(PASS))SprintFunc的实现是返回c.wrap(fmt.Sprint(a...))第 336-340 行即返回一个已经包好转义序列的字符串因此可以安全地拼进fmt.Printf的任意占位符。RedString、GreenString等包级函数则是colorString的快捷封装第 468-542 行内部同样走缓存的 Color 对象 SprintFunc/SprintfFunc。这里有一个 Windows 平台的细节值得注意color.Output不是普通的os.Stdout而是 colorable.NewColorableStdout()——即经 go-colorable 包装的标准输出 writer只有写到color.Output上Windows 下转义序列才会被正确渲染。因此 README 特别强调Windows 下把输出目标改为color.Output。七、接入现有代码全局 Set / Unset第六类用法影响的是此后所有普通输出适合快速改造已有打印代码// Use handy standard colors color.Set(color.FgYellow) fmt.Println(Existing text will now be in yellow) fmt.Printf(This one %s\n, too) color.Unset() // Dont forget to unset // You can mix up parameters color.Set(color.FgMagenta, color.Bold) defer color.Unset() // Use it in your function fmt.Println(All text will now be bold magenta.)源码层面Set / Unsetfunc Set(p ...Attribute) *Color { c : New(p...) c.Set() // 立即向 Output 写入 SGR 序列 return c } func Unset() { if NoColor { return } fmt.Fprintf(Output, %s[%dm, escape, Reset) }Set只是把转义序列裸写到全局Output上之后的fmt.Println自然处于该样式之下直到Unset写出 Reset 序列。使用时的约束Set与Unset必须成对出现README 推荐defer color.Unset()放在函数开头防止遗漏导致后续输出染色泄漏。与第五节不同Set没有返回值可组合且作用于进程全局输出流适合局部代码块而非跨包基础设施。八、禁用/启用颜色输出NO_COLOR、NoColor 与单对象开关README 的Disable/Enable color一节是工程落地中最关键的部分分三层机制1. 自动检测go-isattygo-isatty包会自动对非 tty 输出流例如管道到less禁用颜色。对应源码中NoColor的初始化第 15-36 行NoColor noColorIsSet() || os.Getenv(TERM) dumb || (!isatty.IsTerminal(os.Stdout.Fd()) !isatty.IsCygwinTerminal(os.Stdout.Fd()))即以下任一条件成立即全局禁用颜色设置了NO_COLOR环境变量非空即生效、TERMdumb、标准输出不是终端且非 Cygwin 终端。2. 全局程序化开关CLI 应用中典型的-no-color布尔 flag 用法var flagNoColor flag.Bool(no-color, false, Disable color output) if *flagNoColor { color.NoColor true // disables colorized output }3. 单对象开关对某个 Color 实例单独禁用/启用不影响全局c : color.New(color.FgCyan) c.Println(Prints cyan text) c.DisableColor() c.Println(This is printed without any color) c.EnableColor() c.Println(This prints again cyan...)源码中DisableColor/EnableColor设置的是对象内嵌的noColor *bool字段第 389-410 行而isNoColorSet()的判定顺序是对象级开关优先回落到全局 NoColorfunc (c *Color) isNoColorSet() bool { // check first if we have user set action if c.noColor ! nil { return *c.noColor } // if not return the global option return NoColor }此外New()中有一个容易被忽略的细节若创建对象时NO_COLOR已设置会直接把该对象的noColor初始化为true第 122-124 行因此NO_COLOR环境下创建的 Color 实例默认就是禁用状态且之后仍可被EnableColor()显式覆盖。CI 场景补充README 指出在 GitHub Actions 等支持 ANSI 的 CI 系统中非 tty 检查会导致颜色被静默关闭需要显式设置color.NoColor false绕过检测。scan4all 作为高频输出扫描结果的 CLI 工具这一点对结果日志是否带色的控制策略同样适用。九、属性码速查表由源码整理基于 color.go 的常量定义常用Attribute取值如下便于直接组合类别常量示例SGR 码段说明基础格式Reset、Bold、Faint、Italic、Underline、BlinkSlow、ReverseVideo、Concealed、CrossedOut0~9Reset0用于 Unset前景色FgBlack~FgWhite30~378 色标准前景高亮前景FgHiBlack~FgHiWhite90~97高亮前景背景色BgBlack~BgWhite40~478 色背景高亮背景BgHiBlack~BgHiWhite100~107高亮背景打印路径汇总Print/Printf/Println写全局OutputFprint/Fprintf/Fprintln与SetWriter/UnsetWriter写指定 writerSprint/Sprintln/Sprintf与SprintFunc/SprintfFunc/SprintlnFunc返回包好转义序列的字符串XXString是后者的包级快捷入口。十、对照阅读scan4all 自研 color 包如何实现同样的规范最后回到仓库内部视角。pkg/kscan/lib/color/color.go 展示了同一套 ANSI SGR 规范的另一种实现风格可与 fatih/color 相互印证属性以名字→数字字典表达colorMapred:31、green:32…、backgroundMapred:41…、formatMapbold:1、italic:3、underline:4、overturn:7码段与 fatih/color 的常量定义完全一致核心函数convANSI第 48-65 行把格式、背景、前景码以;连接后生成\x1b[...m文本\x1b[0m等价于 fatih/color 的sequence()format()unformat()组合通过全局开关mod控制是否输出颜色mod0时原样返回字符串对应 fatih/color 的NoColor全局开关但判断粒度是包级而非对象级全局两级。对比可以看出fatih/color 的优势在于自动 tty 检测、NO_COLOR/TERM 环境变量支持、Windows colorable 适配、线程安全的对象缓存自研包的优势在于极简、可静态分析、开关可控。对需要在 scan4all 体系内新增彩色输出的模块建议优先评估 vendored 的 fatih/color能力完整同时参考 slog 包Logger 接口 modifier 修饰函数的组合方式保持输出风格统一。小结围绕 vendor/github.com/fatih/color/README.md 这份依赖文档本文完成了对 fatih/color 全部七类 API 的逐条落地讲解并用 vendor/github.com/fatih/color/color.go 源码验证了每个 API 的底层行为Color.params切片与sequence()决定 SGR 序列内容SetWriter/UnsetWriter的设置-延迟复位模式保证了输出流的状态一致性isNoColorSet()的两级判定对象级优先、全局兜底配合NO_COLOR/TERMdumb/非 tty 自动检测构成了完整的颜色降级机制而colorsCache让高频调用下的对象复用保持零成本。掌握这套机制后无论是为安全扫描工具编写彩色日志还是理解 pkg/kscan/lib/color/color.go、pkg/kscan/core/slog/slog.go 这类仓库内自研实现都能从转义序列如何生成、何时被抑制的角度给出准确判断。【免费下载链接】scan4allOfficial repository vuls Scan: 15000PoCs; 23 kinds of application password crack; 7000Web fingerprints; 146 protocols and 90000 rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表