first commit
This commit is contained in:
241
README.md
Normal file
241
README.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# 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-сообщения, но порядок в этом случае не
|
||||
гарантируется.
|
||||
|
||||
## Установка
|
||||
|
||||
Нужен 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
|
||||
обычная работа возобновится.
|
||||
Reference in New Issue
Block a user