EFK 中使用 ruby 和 javascript 脚本去掉日志中颜色字符详解

1、解释下如下配置

bash 复制代码
filter {
  ruby {
    code => '
      msg = event.get("message")
      if msg
        msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
        event.set("message", msg)
      end
    '
    }
} 

这是 Logstash pipeline 的 filter 配置 ,用 Ruby 代码把日志里的 ANSI 颜色控制符(比如带颜色的终端输出)清理掉。

逐行解释如下👇


✅ 配置整体结构

复制代码
filter {
  ruby {
    code => ' ... Ruby 脚本 ... '
  }
}

意思:

  • filter { ... }

    • Logstash 处理事件阶段
  • ruby { ... }

    • 使用 Ruby 插件执行自定义逻辑
  • code => ' ... '

    • Ruby 代码写在单引号字符串里

🧠 代码逻辑拆解

代码内容:

ruby 复制代码
msg = event.get("message")
if msg
  msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
  event.set("message", msg)
end

逐句解释:

1️⃣ 取日志字段

复制代码
msg = event.get("message")

从 Logstash 事件中获取 message 字段

(也就是 Filebeat 发过来的原始日志内容)


2️⃣ 判断 message 是否存在

复制代码
if msg

避免 message 为空时报错


3️⃣ 正则删除 ANSI 转义字符

复制代码
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")

这一行是关键:

  • \x1B = ESC 字符

  • \[[0-?]*[ -\/]*[@-~]

    • 标准 ANSI 控制码格式

    • 如:

      • \u001b[31m(红色)
      • \u001b[0m
      • \u001b[1;32m
      • etc

👉 作用:去掉日志里的颜色和控制字符


4️⃣ 把清洗后的值写回

复制代码
event.set("message", msg)

覆盖原 message 字段

现在 ES/Kibana 里看到的就是干净的日志


🎯 实际解决的问题

很多容器 / Python / Java 应用日志启用了彩色输出,例如:

复制代码
^[[32mINFO^[[0m Service started

在 Kibana 里很恶心,还可能导致解析失败

这个 ruby 过滤器就是用来:

✔️ 去掉 ^[[32m ^[[0m

✔️ 保留纯文本内容


✅ 你现在的结构写得是正确的

复制代码
filter {
  ruby {
    code => '...'
  }
}

这是标准写法 👍


如果你还想扩展:

  • 只对某些索引清理
  • 或者 message 换成 log 字段
  • 或想用 mutate/gsub 替代 ruby

我也可以帮你优化版本 👌

2、msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "") 详细解释下这个

很好,这一行是整个配置里"最有技术含量"的地方 👇

ruby 复制代码
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")

作用:
把终端 ANSI 转义控制序列(颜色 / 高亮 / 光标控制等)全部删除


一、整体结构先看懂

Ruby 的 gsub

复制代码
gsub(正则, 替换内容)

意思:

把字符串里 所有匹配该正则的内容替换为空字符串

➡️ 所以这行代码是:删除 ANSI 控制码


二、正则逐段拆解(最关键)

完整正则:

复制代码
\x1B\[[0-?]*[ -\/]*[@-~]

ANSI 控制序列的标准格式叫 CSI(Control Sequence Introducer)

一般长这样:

复制代码
ESC [ parameters ; more params command

例如:

复制代码
\x1b[31m
\x1b[0m
\x1b[1;32m
\x1b[1;31;40m
\x1b[2J
\x1b[H

这正则就是 专门为 CSI 这种格式写的


1️⃣ \x1B

复制代码
\x1B

十六进制 1B → ESC 字符

也可以写成:

复制代码
\u001b
\033

👉 说明:所有 ANSI 控制码都以 ESC 开头


2️⃣ \[

复制代码
\[

字面意义的 [

(CSI 开头是 ESC + [


3️⃣ [0-?]*

复制代码
[0-?]*

这一段允许:

复制代码
0 1 2 ... 9  ;  < = > ?

也就是 ANSI 参数部分:

  • 31
  • 0
  • 1;32
  • 38;5;12
  • ?25h
  • 等等

👉 用 * 表示 0 个或多个参数字符


4️⃣ [ -\/]*

复制代码
[ -\/]*

这个字符范围比较怪,看起来难,其实是:

  • ASCII 32(空格) 到 /(47)

也就是 ANSI 里的 intermediate bytes 区间

某些控制序列会用到这一段

例如:

复制代码
ESC [ ? 25 h
ESC [ > 5 m

👉 仍然是 * 表示 可选 & 多个


5️⃣ 最后一段 [@-~]

复制代码
[@-~]

这个是:

  • ASCII @~
  • 范围 64 → 126

ANSI 里这叫 Final Byte(命令字符)

常见的:

字符 含义
m 颜色 / 样式
H 光标移动
J 清屏
K 清行
A B C D 光标方向
s / u 保存/恢复光标
t 窗口控制

👉 只匹配 最后那个命令位


三、举例看它怎么工作

匹配:

复制代码
\x1b[31m
\x1b[1;32m
\x1b[1;31;40m
\x1b[2J
\x1b[K
\x1b[?25h
\x1b[>5m

都会被整段删掉。


四、为什么不用普通简单正则?

你可能见过别人写:

复制代码
/\033\[[0-9;]*m/

这个 只能匹配带 m 的颜色控制

但你的日志可能不止颜色,还可能有:

  • 光标移动
  • 清屏
  • 光标隐藏
  • 终端行为
  • 其他 CSI 控制符

而这一条:

复制代码
\x1B\[[0-?]*[ -\/]*[@-~]

符合 ANSI/VT100 标准的通用匹配表达式,覆盖非常全面,是业界通用方案。


✅ 总结一句

这一行的正则:

👉 精准匹配 所有 ANSI CSI 控制序列

👉 删除日志中终端颜色/控制字符

👉 保留纯文本,保证 ES/Kibana 正常显示


如果你愿意,我还能帮你:

  • 改成 Logstash mutate/gsub(不用 ruby)
  • 或只删除 m 不删光标控制
  • 或仅删除特定颜色控制

你用什么日志源?(Java?Python?K8s?)

我可以帮你做最优版本 👍

3、ESC 是啥

这里的 ESC 指的是 Escape 控制字符 ,不是"退出键"本身,而是 ASCII 表中的一个控制字符

  • ASCII 编码:十进制 27
  • 十六进制0x1B
  • 八进制033
  • 在正则里写成\x1B

在终端里,彩色输出、光标移动、清屏等所谓 ANSI 转义序列(ANSI Escape Sequences) 都是以这个 ESC 字符开头的,例如:

复制代码
ESC [ 31m   --> 设置前景色为红色
ESC [ 0m    --> 重置颜色

写成可见形式就是:

复制代码
\x1B[31m
\x1B[0m

所以你看到的正则:

复制代码
\x1B\[[0-?]*[ -\/]*[@-~]

就是:

先匹配 ESC(\x1B),然后匹配 [ 开头,再匹配后面的参数 + 结尾符,从而 整体匹配并删除 ANSI 颜色/控制码

总结一句:

👉 ESC 是终端控制序列的起始控制字符(ASCII 27),用来触发颜色、光标等控制效果。

4、这个和上边的一样吧,不过使用的是 javascript 脚本

bash 复制代码
processors:
  - script:
      lang: javascript
      id: remove_ansi
      source: >
        function process(event) {
          var msg = event.Get("message");
          if (msg != null) {
            msg = msg.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
            event.Put("message", msg);
          }
        } 

完全一样,功能上 和上面 Ruby 版本是一致的 ,只是写法换成了 JavaScript(Filebeat / Logstash Processor 支持 JS 语言脚本)。

逐行对比解释:


原 Ruby 版本

ruby 复制代码
msg = event.get("message")
if msg
  msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
  event.set("message", msg)
end

JavaScript 版本

javascript 复制代码
function process(event) {
  var msg = event.Get("message");
  if (msg != null) {
    msg = msg.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
    event.Put("message", msg);
  }
}

对比说明

功能 Ruby JS (Filebeat)
取 message event.get("message") event.Get("message")
判断非空 if msg if (msg != null)
替换 ANSI码 msg.gsub(正则, "") msg.replace(正则, "") + g
写回 message event.set("message", msg) event.Put("message", msg)

🔑 注意点

  1. 正则几乎一模一样

    复制代码
    /\x1B\[[0-?]*[ -/]*[@-~]/g
    • \x1B → ESC
    • [0-?]*[ -/]*[@-~] → 匹配 ANSI 控制序列
    • g → 全局匹配(Ruby 的 gsub 默认全局)
  2. 大小写

    • JS 中 event.Getevent.Put 是 Filebeat 内置方法,首字母大写
    • Ruby 是小写 get / set
  3. 功能效果

    • 删除所有 ANSI 转义序列
    • 保留纯文本日志
    • 方便 Kibana/ES 展示

总结

  • 功能上完全等价
  • 只是语言不同:Ruby 版本适合 Logstash filter 插件,JS 版本适合 Filebeat script processor
  • 两者都可以用来清理终端彩色输出

如果你愿意,我可以帮你写一个 同时支持多种日志格式 + JS 去 ANSI 的 Filebeat 脚本示例,直接可用。

你希望我写吗?

相关推荐
Maggie_ssss_supp5 分钟前
Linux-MySQL权限管理
linux·运维·mysql
石像鬼₧魂石7 分钟前
Kali Linux 内网渗透:深度工程实施手册
linux·运维·服务器
筱歌儿1 小时前
TinyMCE-----word表格图片进阶版
开发语言·javascript·word
LXY_BUAA1 小时前
《source insight》添加对.s文件的支持
linux
fai厅的秃头姐!1 小时前
01-python基础-day02Linux基础
linux
好评1241 小时前
git常见操作及问题
linux·git
Ama_tor2 小时前
obsidian进阶の插件系列|Templater从小白到菜鸟
javascript·markdown·插件·obsidian
wuhen_n2 小时前
初识TypeScript
javascript·typescript
不会代码的小猴2 小时前
Linux环境编程第一天笔记
linux·笔记
optimistic_chen2 小时前
【Docker入门】cgroups 资源控制
linux·运维·ubuntu·docker·容器·cgroup