Termux стал удобной платформой для полевых работ: диагностика, автоматизация, сбор телеметрии и журналов. Однако, когда требуется аналитика по событиям на большом числе устройств или узлов, одного локального просмотра логов недостаточно. Решение — централизовать журналы и дать удобный поиск и визуализацию.
В этой статье Денис Евгеньевич, ведущий эксперт РыбинскЛАБ, покажет практический подход к управлению системными журналами через journalctl (systemd-journald) в контуре Termux и дальнейшему маршрутизированию событий в Elastic Stack: сбор/агрегацию (Logstash), хранение (Elasticsearch) и поиск/дешборды (Kibana).
Что именно будем собирать: model журнала и источники
Системные журналы обычно доступны через journalctl и содержат метаданные: единицу (unit), приоритет (priority), временную метку, hostname и PID. Наша цель — превратить события из journald в поток структурированных документов для индексации в Elasticsearch.
Возможные источники событий:
- события systemd (службы и единицы):
UNIT/ unit; - ошибки приложений, которые пишут в journald;
- события ядра (при наличии в journald);
- системные сообщения в пределах узла, где работает Termux.
Условия и оговорки
Termux сам по себе не является полноценным systemd-контейнером на всех устройствах. Поэтому подход зависит от того, как именно у вас организован доступ к journalctl:
- Если на устройстве/среде фактически запущен systemd-journald, то
journalctlможет быть доступен напрямую. - Если systemd-journald находится в другой среде (например, отдельный Linux-слой/контейнер/виртуальная машина), Termux может работать как клиент, передающий запросы и/или читающий выгрузки журналов.
Независимо от архитектуры, базовая идея одинакова: получать события в формате, пригодном для транспортировки, добавить метаданные (host, service, severity), отправить в Logstash/Elasticsearch.
Подготовка Termux: инструменты и доступ к journalctl
На стороне Termux подготавливаем базовые утилиты. В зависимости от окружения может потребоваться отдельная установка util-linux, coreutils, а также инструменты для сети.
pkg update
pkg upgrade
pkg install curl jq nano
Далее проверяем наличие journalctl:
command -v journalctl || which journalctl
journalctl --version || true
Если команда недоступна, это сигнал, что требуется другой путь: чтение экспорта журналов, доступ к journald из окружения, либо использование альтернативного источника логов (например, файлы, которые пишутся приложениями). В этой статье фокус — именно workflow вокруг journalctl.
Экспорт событий из journalctl: фильтрация и форматирование
Ключ к интеграции — получить данные из journald в предсказуемом формате. Практичный вариант — JSON-вывод.
Пример: чтение последних событий с ограничением по времени и выводом в JSON.
journalctl -u ssh --since "-1 hour" -o json-pretty
Для потоковой отправки лучше использовать не «pretty», а компактный JSON. Часто используют -o json.
journalctl -u ssh --since "-10 minutes" -o json
Добавим базовую фильтрацию по приоритету (например, ошибки). В journald priority обычно: 0..7, где 0 — emergency, 3 — error (в зависимости от конфигурации). На практике удобнее начинать с --priority и тестировать.
journalctl --since "-30 minutes" --priority=3 -o json
Добавление метаданных: hostname, environment, service
Elastic Stack лучше работает с унифицированной схемой. Мы добавим поля на этапе преобразования. Самый простой способ в Termux — через jq дописать/нормализовать структуру.
Пример преобразования одного JSON-события: извлекаем ключевые поля и приводим их к целевому формату.
journalctl -u ssh --since "-10 minutes" -o json \
| jq -c '{
"@timestamp": .REALTIME_TIMESTAMP,
"host": (.SYSLOG_HOST // "unknown"),
"unit": (.SYSLOG_IDENTIFIER // ._SYSTEMD_UNIT // "unknown"),
"priority": .PRIORITY,
"message": (.MESSAGE // "")
}'
Важно: REALTIME_TIMESTAMP — это числовой timestamp в формате journald. Его обычно нужно конвертировать к ISO8601 или к формату, который понимает Elasticsearch. Ниже мы покажем практичный вариант отправки с нормализацией на стороне Logstash.
Схема централизованного контура: Termux → Logstash → Elasticsearch → Kibana
Рекомендуемая схема для централизации:
- Termux: вычитывает события из
journalctl, формирует события в JSON и отправляет их в Logstash (обычно по HTTP или TCP). - Logstash: принимает входящие события, нормализует поля, обогащает (например, service/level), определяет индекс и отправляет в Elasticsearch.
- Elasticsearch: хранит документы и обеспечивает индексацию/поиск.
- Kibana: строит запросы, визуализации, алерты (если настроены).
Такой подход удобен для лабораторий и эксплуатационных сценариев: вы контролируете схему данных и процесс агрегации.
Вариант транспорта: HTTP от Termux в Logstash
На стороне Termux проще отправлять JSON постом. Пример подготовки одного события (или итерации по событию) зависит от того, как вы хотите шить поток: батчами или поштучно. Для демонстрации используем поштучный формат и отправку через curl.
Ниже — пример «прослойки» (скриптовый подход) без претензии на идеальную производительность, с акцентом на корректность схемы.
LOGSTASH_URL="http://192.168.1.10:8080/event"
journalctl --since "-5 minutes" -o json \
| jq -c '{
"@source": "termux-journalctl",
"host": (.SYSLOG_HOST // "unknown"),
"unit": (. _SYSTEMD_UNIT // .SYSLOG_IDENTIFIER // "unknown"),
"priority": .PRIORITY,
"message": (.MESSAGE // ""),
"realtime_timestamp": .REALTIME_TIMESTAMP
}' \
| while read -r event; do
curl -sS -X POST "$LOGSTASH_URL" \
-H 'Content-Type: application/json' \
-d "$event" >/dev/null
done
Примечание: показан пример с while read. На проде стоит использовать батчирование и контроль ошибок/ретраев.
Если вы применяете VPN, то только для создания локальной сети и связности устройств в рамках инфраструктуры — не для обхода блокировок. В этом случае Logstash будет доступен по адресам локального сегмента.
Конфигурация Logstash: вход, нормализация, индексация
Далее зададим конфигурацию Logstash. Здесь показан пример входа по HTTP и сохранения в Elasticsearch.
Пример pipeline для logstash.conf:
input {
http {
port => 8080
codec => json
# Ожидаем: единичные JSON-события, отправляемые Termux
}
}
filter {
# realtime_timestamp из journald конвертируем.
# REALTIME_TIMESTAMP обычно: микросекунды с эпохи.
# Переведем в миллисекунды для @timestamp.
ruby {
code => '
rt = event.get("realtime_timestamp")
if rt
# rt в микросекундах → миллисекунды
event.set("@timestamp", (rt.to_f / 1000).to_i)
end
'
}
# Приводим @timestamp к формату, который понимает ES.
date {
match => [ "@timestamp", "UNIX_MS" ]
target => "@timestamp"
}
mutate {
# Нормализуем поля
rename => { "unit" => "service" }
remove_field => [ "realtime_timestamp" ]
}
# Пример маппинга priority в уровень (очень грубо, для иллюстрации)
ruby {
code => '
p = event.get("priority")
level = case p
when 0..1 then "emergency"
when 2 then "alert"
when 3 then "error"
when 4..6 then "warning"
else "info"
end
event.set("level", level)
'
}
}
output {
elasticsearch {
hosts => ["http://192.168.1.20:9200"]
index => "termux-journalctl-%{+YYYY.MM.dd}"
}
}
Смысл: Logstash принимает JSON, нормализует timestamp, формирует индекс по дате и записывает документы в Elasticsearch.
Настройка Elasticsearch и индексов: mapping и шаблоны
Чтобы поиск и агрегации работали предсказуемо, заранее полезно задать mapping (или использовать шаблон индекса). Минимально:
@timestamp— date;host,service,level— keyword;message— text (и возможно keyword под точные совпадения);priority— integer.
Если вы используете шаблоны через Index Template, вы управляете типами полей. В рамках статьи приведем пример логики, а конкретный curl зависит от версии Elastic.
Kibana: поиск, фильтры и готовые запросы
После поступления данных в индексы termux-journalctl-* в Kibana можно:
- выбрать Data View по шаблону;
- сделать Discover-поиск по
service,host,levelи текстуmessage; - создать Lens/Viz для распределений событий по времени.
Примеры запросов в Discover (KQL):
- ошибки сервиса:
service:"ssh" and level:"error" - события конкретного узла:
host:"device-01" - за период (через Time Picker):
last 15 minutes - по тексту:
message:"Failed"
Потоковый сбор: journalctl -f и «живые» события
Для живого мониторинга можно использовать режим слежения:
journalctl -f -u ssh -o json \
| jq -c '{
"@source": "termux-journalctl",
"host": (.SYSLOG_HOST // "unknown"),
"service": (. _SYSTEMD_UNIT // .SYSLOG_IDENTIFIER // "unknown"),
"priority": .PRIORITY,
"message": (.MESSAGE // ""),
"realtime_timestamp": .__REALTIME_TIMESTAMP
}' \
| while read -r event; do
curl -sS -X POST "$LOGSTASH_URL" \
-H 'Content-Type: application/json' \
-d "$event" >/dev/null
done
При таком подходе важно учесть:
- устойчивость сети и повторные попытки;
- нагрузку на Logstash/Elasticsearch;
- идемпотентность (если возможны повторы при реконнекте);
- ротацию и backpressure (на уровне клиента — хотя бы логирование ошибок отправки).
Агрегация и хранение: что улучшает Elastic Stack
Централизация через Elastic дает:
- Единый поиск по всем узлам и всем типам событий (в пределах вашей схемы).
- Горизонтальную масштабируемость хранения и поисковых запросов.
- Возможность агрегаций: по сервисам, хостам, уровням, временным окнам.
- Дешборды и отчеты: динамика ошибок, пики, частотность сообщений.
Если вы расширите модель (добавите кореляцию по PID/TRANSACTION_ID, группировку по unit, обогащение гео/инвентаризацией узлов), ценность системы резко вырастет.
Безопасность и эксплуатация
В зависимости от требований:
- используйте изоляцию сети (VLAN/локальный сегмент), а при необходимости — локальную сеть через VPN;
- ограничивайте доступ к Logstash endpoint и Elasticsearch (firewall, правила;
- по возможности включайте TLS для HTTP между Termux и Logstash;
- ведёте мониторинг Logstash и Elasticsearch (очереди, latency, reject, pipeline failures).
Даже в лабораторной среде лучше сразу заложить контроль, чтобы система не «разрослась» и не потеряла стабильность.
Чек-лист внедрения
- Проверьте наличие
journalctlи доступность событий. - Определите фильтры:
-u,--since,--priority. - Согласуйте схему полей документа:
@timestamp,host,service,level,message. - Настройте Logstash input/filter/output и индексацию.
- Создайте Data View в Kibana и валидируйте запросы.
- Добавьте тестовый поток, затем включите мониторинг и алертинг (при необходимости).
Заключение
Мы рассмотрели практический workflow для управления системными журналами через journalctl в Termux и их централизованный сбор в Elastic Stack: от фильтрации и форматирования событий до нормализации в Logstash, индексации в Elasticsearch и поиска/аналитики в Kibana. Такой подход дает единый контур диагностики, ускоряет расследования и помогает строить прозрачные наблюдаемости.
Если вам нужна помощь с внедрением под вашу инфраструктуру (схема индексов, оптимизация pipeline Logstash, настройка надежной доставки, шаблоны и dashboards), команда РыбинскЛАБ поможет спроектировать и развернуть решение под ваши требования.