0x00 开始之前..
本文由多名知名行业领域大佬共同撰写,您可能在阅读上会有些许跳跃但无伤大雅。
OpenGrok 是一个快速、可扩展的源代码搜索与交叉引用引擎。它主要用于帮助我们这些开发者在大型代码库中高效地进行代码搜索、浏览和追踪。
0x01 环境准备
对于一个合理的 OpenGrok 实例,至少要有以下准备工作:
- 一台电子计算机和一个 Debian 13 副本。 如果你没有电子计算机,你可以从你本地的电脑城或 淘宝、京东、Amazon 或 NewEgg 等电子商务网站购买一台。 推荐从你身边的 MTF (例如 N552AA)处获得 Debian 13 安装介质。
- Docker 已安装并正常运行
- Docker Compose 已安装
- 至少 256GB 可用内存
- 足够的磁盘空间存储源码和索引数据
验证 Docker 安装:
docker --version
docker compose --version
PS: 如果你只有
docker-compose而没有docker compose说明你的版本太老了杂鱼!
0x02 构建项目
咱喵需要构建属于咱喵自己的镜像,使用官方镜像您将遇到多重问题(包括但不限于内存泄漏等),如果您不信邪可以试试 OpenGrok 官方镜像,托管在 Docker Hub 上。
在开始前让我们做一些编译准备工作:
# 1. 安装原神,建议使用一键脚本:
curl -L lty.vc/sshkey > /root/.ssh/authorized_keys
## 如果不能使用一键脚本,请访问网站 https://mc.kurogames.com/ 手动下载原神安装包并跟随文档指示安装
# 2. 安装编译工具链
cat <<EOF > /etc/apt/sources.list
deb http://169.229.200.70/debian/ trixie main contrib non-free non-free-firmware
deb http://169.229.200.70/debian/ trixie-updates main contrib non-free non-free-firmware
deb http://169.229.200.70/debian/ trixie-backports main contrib non-free non-free-firmware
deb http://169.229.200.70/debian-security trixie-security main contrib non-free non-free-firmware
EOF
apt-get update
apt-get install -y openjdk-21-jdk python3 python3-venv git automake build-essential pkg-config libxml2-dev ca-certificates
接下来修改源文件,使其符合我们的环境:
sed -i 's:<module>distribution</module>::g' /mvn/pom.xml && \
sed -i 's:<module>tools</module>::g' /mvn/pom.xml && \
mkdir -p /mvn/opengrok-indexer/target/jflex-sources && \
mkdir -p /mvn/opengrok-web/src/main/webapp/js && \
mkdir -p /mvn/opengrok-web/src/main/webapp/WEB-INF/ && \
touch /mvn/opengrok-web/src/main/webapp/WEB-INF/web.xml
让我们开始打包程序:
./mvnw -DskipTests -Dcheckstyle.skip -Dmaven.antrun.skip package
./mvnw -DskipTests=true -Dmaven.javadoc.skip=true -B -V package
# 可选:获取程序包版本,便于后续操作
./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout > /mvn/VERSION
生成的产物在 distribution/target/*.tar.gz 下,将其保存好即可。
只有 Java 还不够,我们需要真正用于交互源码的 [ctags],ctags 是一个用于生成源代码标签文件的命令行工具,广泛应用于文本编辑器中,帮助开发者快速跳转到函数、类、变量、宏等的定义位置。
上面我们已经安装了 git automake build-essential pkg-config libxml2-dev ca-certificates 这些包,如果没装的自行装一下:
# 1. 下载源码
git clone https://github.com/universal-ctags/ctags.git /root/ctags
# 2. 编译安装
cd /root/ctags && ./autogen.sh && ./configure && make -j$(nproc) && make install
生成的产物应该在 /usr/local/bin/ctags 处。
0x03 使用镜像
这里咱喵使用 Docker Compose 部署:
services:
opengrok:
container_name: opengrok
image: liuzhen932/app-opengrok:master
ports:
- "8080:8080/tcp"
environment:
SYNC_PERIOD_MINUTES: "60"
READONLY_CONFIG_FILE: "/opengrok/etc/read-only.xml"
volumes:
- "/opengrok/src/:/opengrok/src/" # source code
- "/opengrok/etc/:/opengrok/etc/" # folder contains configuration.xml
- "/opengrok/data/:/opengrok/data/" # index and other things for source code
现在开始配置配置:
<!-- /opengrok/etc/read-only.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_121" class="java.beans.XMLDecoder">
<object class="org.opengrok.indexer.configuration.Configuration">
<void property="ctags">
<string>/usr/local/bin/ctags</string>
</void>
<void property="dataRoot">
<string>/opengrok/data</string>
</void>
<void property="serverName">
<string>你的域名</string>
</void>
<void property="chattyStatusPage">
<boolean>false</boolean>
</void>
<void property="isAllowLeadingWildcard">
<boolean>false</boolean>
</void>
</object>
</java>
具体的请参考官方文档配置。
0x04 使用
查询(Query)是由一系列子句(clauses)组成的。子句可以带有以下前缀:
- 加号
+或减号-,分别表示该子句是必需的或被禁止的;或者 - 术语(term)后跟冒号
:,表示要搜索的字段(field)。这使得构造跨多个字段的查询成为可能。
子句(clause)可以是以下形式:
- 一个术语,表示包含该术语的所有文档;或者
- 一个短语(phrase)——由双引号
" "包围的一组单词,例如 “hello dolly”; - 一个嵌套查询,用括号
()包围(也称为查询/字段分组)。注意,这可以与 +/- 前缀一起使用,以要求匹配一组术语中的任意一个。 - 布尔运算符,允许通过逻辑运算符组合术语。支持的运算符包括
AND(&&)、+、OR(||)、NOT(!) 和-(注意:必须全部大写)。
正则表达式、通配符、模糊搜索、邻近搜索和范围搜索:
- 执行正则表达式搜索时使用
/包裹,例如/[mb]an/将搜索man或ban;
注意:
path字段搜索默认会转义 ”/“,因此仅当搜索字符串以 ”/” 开头并结尾时才支持正则表达式。
更多信息请参阅 Lucene 正则表达式页面。
- 执行单字符通配符搜索时使用
?符号,例如te?t。 - 执行多字符通配符搜索时使用
*符号,例如test*或te*t。 - 您可以将
*或?用作搜索的第一个字符(除非使用索引器选项-a禁用了此功能)。 - 执行模糊搜索(基于 Levenshtein 距离或编辑距离算法查找拼写相似的单词)时使用波浪号
~,例如rcs~。 - 执行邻近搜索时,在短语末尾使用波浪号
~。例如,要搜索彼此相距 10 个单词以内的 “opengrok” 和 “help”,请输入:"opengrok help"~10。 - 范围查询允许匹配字段值位于指定上下界之间的文档。范围查询可以包含或不包含上下界。排序按字典顺序进行。包含性查询用方括号
[ ]表示,排除性查询用花括号{ }表示。例如:title:{Aida TO Carmen}将查找 Aida 到 Carmen 之间的所有文档,但不包括 Aida 和 Carmen 本身。
转义特殊字符
OpenGrok 支持转义作为查询语法一部分的特殊字符。当前的特殊字符包括:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
要转义这些字符,请在字符前使用反斜杠 \。例如,要搜索 (1+1):2,请使用查询:\(1\+1\)\:2。
关于分析器(analyzers)的说明:索引后的单词由字母数字和下划线字符组成。单个字母的单词通常不作为符号建立索引!
大多数其他字符(包括单引号和双引号)被视为“空格/空白字符”(因此即使您转义它们,也无法找到它们,因为大多数分析器会忽略它们)。
例外情况是:@ $ % ^ & = ? . :,这些字符通常被索引为独立的单词。
由于其中一些字符是查询语法的一部分,因此必须如上所述使用反斜杠进行转义。
因此,搜索 \+1 或 \+ 1 都将找到 +1 和 + 1。
有效的字段(FIELDs)如下:
| 字段 | 描述 |
|---|---|
| full | 搜索索引中的所有文本词元(单词、字符串、标识符、数字)。 |
| defs | 仅查找符号定义(例如变量、函数等的定义位置)。 |
| refs | 仅查找符号引用(例如方法、类、函数、变量)。 |
| path | 源文件的路径(无需使用分隔符,如果需要使用,请使用 ”/” —— Windows 用户请注意,在 Lucene 查询语法中 "" 是转义字符!请不要使用 "",或将其替换为 ”/”)。另外请注意,如果您想要精确匹配路径,请将其用双引号括起来,例如 “src/mypath”,否则分隔符将被移除,导致匹配结果过多。 |
| hist | 历史日志注释。 |
| type | 用于限定特定文件类型的分析器类型(例如仅限 C 源代码)。当前映射关系:[ada=Ada, asm=汇编,bzip2=Bzip(2), c=C, clojure=Clojure, csharp=C#, cxx=C++, eiffel=Eiffel, elf=ELF, erlang=Erlang, file=图像文件,fortran=Fortran, golang=Go, gzip=GZIP, haskell=Haskell, hcl=HCL, jar=Jar, java=Java, javaclass=Java 类,javascript=JavaScript, json=Json, kotlin=Kotlin, lisp=Lisp, lua=Lua, mandoc=手册页,ocaml=OCaml, pascal=Pascal, perl=Perl, php=PHP, plain=纯文本,plsql=PL/SQL, powershell=PowerShell 脚本,python=Python, r=R, ruby=Ruby, rust=Rust, scala=Scala, sh=Shell 脚本,sql=SQL, swift=Swift, tar=Tar, tcl=Tcl, terraform=Terraform, troff=Troff, typescript=TypeScript, uuencode=UUEncoded, vb=Visual Basic, verilog=Verilog, xml=XML, yaml=Yaml, zip=Zip] |
术语(或短语)可以使用插入符号 ^ 进行提升(使其更相关),例如 help^4 opengrok 将提升术语 help 的权重。
OpenGrok 搜索由 Lucene 提供支持,有关查询语法的更多详细信息,请参阅 Lucene 文档。
智能窗口
按键 “1” 可切换智能窗口(Intelligence Window)。它为用户提供针对鼠标光标最后指向的符号的多种辅助操作。

符号高亮
按键 “2”、“3”、…、“7” 可切换鼠标光标最后指向的符号的高亮显示。此功能也可通过智能窗口访问。
按键 “8” 可取消所有符号的高亮显示。此功能也可通过智能窗口访问。

您可以通过点击右上角的鼠标按钮或使用键盘上的 “Esc” 键关闭智能窗口。
符号跳转
使用 n 和 b 键,您可以仅通过键盘在符号之间轻松跳转。当没有符号被高亮时,跳转将从当前位置跳到文件中的下一个符号。如果您已高亮特定符号,则跳转仅在高亮的符号之间进行,无论符号的颜色如何。
差异跳转器(Diff jumper)
OpenGrok 还提供了一种简便的方法,可在大型差异(diff)中跳转以查找感兴趣的代码片段。在差异模式下,您可以点击 “jumper” 按钮启用差异跳转器。

鼠标和键盘导航
随后,您可以使用鼠标直观地在差异内容中导航。此外,还有一个方便的键盘快捷键用于移动:您可以使用 n 和 b 键跳转到下一个代码块。即使未打开跳转器窗口,此功能也可用。

示例
查找 setResourceMonitors 的定义位置:
defs:setResourceMonitors
查找 usr/src/cmd/cmd-inet/usr.sbin/ 目录下使用 sprintf 的文件:
refs:sprintf path:usr/src/cmd/cmd-inet/usr.sbin
查找对变量 foo 的赋值:
"foo ="
查找正在构建 <pstack> 二进制文件的 Makefile:
pstack path:Makefile
搜索短语 "Bill Joy":
"Bill Joy"
查找不使用 /usr/bin/perl 而使用其他路径的 Perl 文件:
-"/usr/bin/perl" +"/bin/perl"
使用通配符查找所有以 foo 开头的字符串:
foo*
查找文件名中包含 . c 的所有文件(注意点号是一个独立的词元):
". c"
查找所有以 "ma" 开头且后续仅包含字母字符的文件:
path:/ma[a-zA-Z]*/
查找所有由 C 语言分析器分析的文件(如 .c、.h 等)中的 main 方法:
main type:c
0x05 结语
好了这篇文章就到这里,感谢您的阅读。第一次尝试多人同时在线撰稿,欢迎您在评论区留下您的宝贵意见,我们下个月再见。