Files
rb-search/README.md
Alex Shlyakhov be3251716c
Some checks failed
release / release (push) Has been cancelled
Build infrastructure for releases
- Makefile: cross-compile to linux/{amd64,arm64}, darwin/{amd64,arm64},
  windows/amd64 into dist/ with SHA256SUMS. Version is stamped via
  -ldflags '-X main.version=...'.
- .gitea/workflows/release.yml: on tag push (v*) the workflow runs
  `make dist`, creates a Gitea release for the tag and uploads every
  artefact from dist/ via the Gitea API.
- main.go: `rb-search version` / --version prints the stamped version.
- README: new "Готовые бинари" section with curl/Invoke-WebRequest
  install snippets and a checksum-verify hint.
2026-05-26 13:46:16 +05:00

269 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# rb-search
Консольная утилита для поиска по сообщениям в очередях RabbitMQ **без их потребления**.
## Что делает
1. Считывает глубину очереди `N` через `queue.declare-passive`.
2. Делает `N` раз `basic.get` с `autoAck=false` — сообщения становятся `unacked`,
для других консьюмеров очередь выглядит пустой, но физически они остаются на брокере.
3. В памяти проверяет каждое тело на подстроку и печатает совпадения (или все
сообщения, если фильтр не задан).
4. Делает `basic.nack(requeue=true)` по delivery-тегам **в обратном порядке**
каждое `nack` возвращает сообщение в голову очереди, и после прохода
очередь восстанавливается в исходном виде. Без дублей, без потери
`properties` / `headers` (сообщения ни разу не публикуются заново — это те же
фреймы с другим ack-состоянием).
На любой ветке выхода (ошибка, Ctrl+C, паника) defer гарантирует reverse-nack
до закрытия канала. Если по какой-то причине nack не успел — закрытие канала
автоматически возвращает unacked-сообщения, но порядок в этом случае не
гарантируется.
## Установка
### Готовые бинари (рекомендуется)
Собранные релизы лежат на странице
[Releases](https://git.arx.ru/shuricken/rb-search/releases) — Linux/macOS/Windows,
amd64 и arm64. Скачать соответствующий файл, проверить контрольную сумму
из `SHA256SUMS` и положить на `PATH`:
```bash
# Linux/macOS, под свою архитектуру
curl -LO https://git.arx.ru/shuricken/rb-search/releases/download/vX.Y.Z/rb-search-vX.Y.Z-linux-amd64
curl -LO https://git.arx.ru/shuricken/rb-search/releases/download/vX.Y.Z/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
chmod +x rb-search-*
sudo mv rb-search-* /usr/local/bin/rb-search
```
```powershell
# Windows PowerShell
Invoke-WebRequest -OutFile rb-search.exe `
https://git.arx.ru/shuricken/rb-search/releases/download/vX.Y.Z/rb-search-vX.Y.Z-windows-amd64.exe
Move-Item rb-search.exe $env:USERPROFILE\bin\
```
Проверка установки: `rb-search version` → печатает версию.
### Из исходников
Нужен Go 1.22+. Бинарь самодостаточный, без внешних зависимостей в рантайме.
#### Любая ОС
```bash
git clone ssh://git@git.arx.ru:2222/shuricken/rb-search.git
cd rb-search
go build -o rb-search .
```
Готовый бинарь — `./rb-search`. Положить на `PATH`:
- Linux/macOS: `install -m 0755 rb-search ~/.local/bin/` или `sudo mv rb-search /usr/local/bin/`
- Windows (PowerShell): `Move-Item rb-search.exe $env:USERPROFILE\bin\`
#### Через `go install`
```bash
go install git.arx.ru/shuricken/rb-search@latest
```
Бинарь окажется в `$(go env GOBIN)` (по умолчанию `~/go/bin`). Добавить в `PATH`:
- bash/zsh: `export PATH="$PATH:$(go env GOPATH)/bin"` в `~/.bashrc` / `~/.zshrc`
- fish: `fish_add_path (go env GOPATH)/bin`
- Windows: `setx PATH "%PATH%;%USERPROFILE%\go\bin"` (новые терминалы)
#### Arch Linux
```bash
sudo pacman -S go
go install git.arx.ru/shuricken/rb-search@latest
```
#### Debian / Ubuntu
```bash
sudo apt install golang-go
go install git.arx.ru/shuricken/rb-search@latest
```
Если в репозитории старый Go (< 1.22) — собрать из исходников после установки
`go` через `snap` или `gvm`.
#### macOS
```bash
brew install go
go install git.arx.ru/shuricken/rb-search@latest
```
#### Windows
1. Поставить Go с https://go.dev/dl/.
2. В PowerShell: `go install git.arx.ru/shuricken/rb-search@latest`.
3. Бинарь окажется в `%USERPROFILE%\go\bin\rb-search.exe`.
#### Кросс-компиляция
С Linux собрать под другую платформу:
```bash
GOOS=darwin GOARCH=arm64 go build -o rb-search-darwin-arm64 .
GOOS=windows GOARCH=amd64 go build -o rb-search.exe .
```
## Конфигурация
Два независимых источника (приоритет — конфиг-файл, если он есть).
### JSON-конфиг
Путь поиска: `--config``$RB_SEARCH_CONFIG``$XDG_CONFIG_HOME/rb-search/config.json`
`~/.config/rb-search/config.json`.
Создать шаблон:
```bash
rb-search init
```
Формат:
```json
{
"default": "prod",
"servers": {
"local": {
"url": "amqp://guest:guest@localhost:5672/"
},
"prod": {
"url": "amqp://admin:secret@rabbit.prod:5672/myvhost"
},
"arx": {
"url": "amqp://admin:REDACTED@10.49.150.156:5672/"
}
}
}
```
Управление:
```bash
rb-search list # показать серверы, default помечен *
rb-search set-default prod # сменить default
```
### Переменные окружения
Если конфиг-файла нет и заданы переменные — синтезируется сервер `env`, он же
default:
```bash
export EVENTBUS_AMQP_HOST=10.49.150.156 # обязательная
export EVENTBUS_AMQP_USER=admin
export EVENTBUS_AMQP_PASS=REDACTED
export EVENTBUS_AMQP_PORT=5672 # опционально, по умолчанию 5672
export EVENTBUS_AMQP_VHOST= # опционально, по умолчанию /
rb-search --queue event
```
Существующий конфиг полностью имеет приоритет — env в этом случае игнорируется,
чтобы поведение было однозначным.
## Использование
```text
rb-search [flags] # читать default-сервер
rb-search --server NAME --queue Q # выбрать сервер вручную
rb-search list # список серверов
rb-search set-default NAME # сменить default
rb-search init # создать sample-конфиг
```
Флаги:
| Флаг | Назначение |
|----------------|-----------------------------------------------------------------------------------------------------|
| `--config PATH`| Путь к конфигу. |
| `--server NAME`| Имя сервера из конфига (override default). |
| `--queue NAME` | Очередь для сканирования (обязательный). |
| `--search S` | Подстрока для поиска в теле. Пусто — печатать все. |
| `--full` | Печатать полный конверт (exchange, routing-key, headers, properties). По умолчанию — только тело. |
| `--json` | Машинный вывод. С `--full` — объект-конверт; без `--full` — стрим тел. |
| `--max-body N` | Обрезать тело до N байт при печати (`0` — без ограничения). |
| `--timeout D` | Таймаут подключения, например `15s`. По умолчанию `30s`. |
### Матрица режимов вывода
| Флаги | stdout |
|-------------------|---------------------------------------------------------------------|
| `(default)` | Тело, pretty-print если JSON, маркер `--- #N tag=… ---` в stderr. |
| `--full` | Конверт + тело (тело pretty-print если JSON), человекочитаемо. |
| `--json` | Стрим тел: компактный JSON (если тело — JSON) или JSON-строка. |
| `--json --full` | Один JSON-объект на строку с полным конвертом; `body` — вложенный JSON, если разбирается. |
Диагностика (`queue "…" depth=N`, `scanned=N matched=M`, маркеры сообщений)
идёт в **stderr**, чтобы stdout оставался парсимым `jq`/файлом.
### Примеры
```bash
# Все сообщения как pretty JSON
rb-search --queue event
# Поиск с подсветкой (ANSI inverse video)
rb-search --queue event --search "OLV-3643"
# Полный конверт в человекочитаемом виде
rb-search --queue event --full
# Стрим тел через jq
rb-search --queue event --json | jq
# Собрать тела в массив
rb-search --queue event --json | jq -s .
# Извлечь поле из каждого тела
rb-search --queue event --json --search change | jq '.offerAcceptance.id'
# Полные сообщения с разобранным body
rb-search --queue event --json --full | jq '.body.action'
# Только тела в файл
rb-search --queue event > bodies.txt # маркеры остались в терминале (stderr)
# Без болтовни
rb-search --queue event --json 2>/dev/null | jq
# Другой сервер из конфига
rb-search --server prod --queue billing.events --search "invoice-42"
# С env-переменными, без конфиг-файла
EVENTBUS_AMQP_HOST=10.49.150.156 EVENTBUS_AMQP_USER=admin EVENTBUS_AMQP_PASS=REDACTED \
rb-search --queue event
```
### Коды выхода
- `0` — успех (включая отсутствие совпадений).
- `1` — ошибка рантайма (нет коннекта, не существует очередь, ошибка AMQP, …).
- `2` — неверное использование флагов.
## Ограничения
- Очередь должна существовать. `queue.declare-passive` сначала пробуется как
`durable`, при mismatch — переоткрывается канал и пробуется как
non-durable. Декларация с `auto-delete=true` / `exclusive=true` может не
совпасть — это редко мешает на практике.
- `basic.get` читает только то, что есть в очереди на момент старта. Сообщения,
пришедшие во время сканирования, будут увидены при следующем запуске.
- Поиск — побайтовый `Contains` по сырому телу. Если тело сжато
(`content-encoding: gzip`), искать нужно по сжатому представлению или
разжимать руками.
- Параллельно работающие консьюмеры на этой же очереди в момент сканирования
будут видеть очередь как «пустую» — это нормально, после reverse-nack
обычная работа возобновится.