Вопрос или проблема
У меня есть строковый ключ с меткой времени, который мне нужно преобразовать в число, потому что strftime
выдает ошибку, что оно должно быть числом.
journalctl -n1 --output=json | jq '.__REALTIME_TIMESTAMP | tonumber |= (. / 1000 | strftime("%Y-%m-%d")), .MESSAGE'
но я получаю ошибки выражения недопустимого пути. Предполагаю, что синтаксис у меня неправильный.
В конечном итоге я хочу отобразить ключ __REALTIME_TIMESTAMP
в читаемом формате и ключ MESSAGE
.
Я не уверен, что вы имеете в виду с |=
здесь.
Это может работать так:
$ journalctl -n1 --output=json |
jq '(.__REALTIME_TIMESTAMP | tonumber/1000000 | strftime("%Y-%m-%d %H:%M:%S")), .MESSAGE'
"2023-11-11 21:44:27"
"[session uid=1000 pid=1420] Activation via systemd failed for unit 'gvfs-daemon.service': Unit gvfs-daemon.service is masked."
Или отформатированный / необработанный вывод:
$ journalctl -n1 --output=json |
jq -r '(.__REALTIME_TIMESTAMP | tonumber/1000000 | strftime("[%Y-%m-%d %H:%M:%S]: ")) + .MESSAGE'
[2023-11-11 21:44:27]: [session uid=1000 pid=1420] Activation via systemd failed for unit 'gvfs-daemon.service': Unit gvfs-daemon.service is masked.
То же самое, но с показом миллисекунд
- используя
@tsv
для показа вывода строка за строкой - используя переключатель
-f
для командыjournalctl
journalctl -axf --output=json |
jq -r '[
( .__REALTIME_TIMESTAMP | tonumber/ 1000000 | strftime("%F %T") )+"."+(
.__REALTIME_TIMESTAMP | tonumber / 1000000 | tostring | split(".")[1] ),
.MESSAGE, .PRIORITY, .SYSLOG_FACILITY, .SYSLOG_IDENTIFIER, ._UID, ._GID
] | @tsv'
2025-02-03 20:38:33.233387 gkr-pam: unlocked login keyring 6 10 mate-screensaver-dialog 1000 1000
2025-02-03 22:16:18.29829 [session uid=1000 pid=4069173] Successfully activated service 'org.freedesktop.Notifications' 6 3 dbus-daemon 1000 1000
2025-02-04 12:03:10.427966 <WpPortalPermissionStorePlugin:0x5592194d1ce0> Failed to call Lookup: GDBus.Error:org.freedesktop.portal.Error.NotFound: No entry for camera 4 1000 1000
В конвейере вы должны использовать stdbuf
:
while IFS=$'\t' read -r date message priority facility syslogid uid gid;do
printf '\e[%sm%-26s %3d %6d %6d %s\e[0m\n' $((priority >= 5 ? 0 : 31 )) \
"$date" "$priority" "$uid" "$gid" "$message"
done < <(
journalctl -axf --output=json |
stdbuf -o0 jq -r '[
( .__REALTIME_TIMESTAMP | tonumber/ 1000000 | strftime("%F %T") )+"."+(
.__REALTIME_TIMESTAMP | tonumber / 1000000 | tostring | split(".")[1] ),
.MESSAGE, .PRIORITY, .SYSLOG_FACILITY, .SYSLOG_IDENTIFIER, ._UID, ._GID
] | @tsv'
)
Будет печатать красным строки с приоритетом меньше 5.
.
Ответ или решение
Вопрос о том, как преобразовать временную метку (timestamp) в число и сделать её читаемой для человека, является важной задачей для многих специалистов в области IT, особенно при работе с журналами системных сообщений. В данном случае используется команда journalctl
для получения записей журнала в формате JSON и инструмент jq
для разбора и обработки данных. Задача усложняется наличием строки временной метки, которую необходимо корректно преобразовать в числовое значение перед применением функции strftime
. Давайте разберем этот процесс подробнее.
Теория
Временные метки обычно хранятся в UNIX-формате времени, что представляет собой количество секунд с 1 января 1970 года (эпоха Unix). В некоторых системах, таких как система журналов Linux, временные метки могут быть представлены в миллисекундах или даже наносекундах, что требует соответствующего деления на 1000 или 1000000 для получения секунд.
Инструмент jq
предоставляет возможность обрабатывать JSON-данные с использованием различных функций, включая tonumber
для преобразования строки в число и strftime
для форматирования числового значения времени в человечески-понятный формат.
Пример
Рассмотрим следующее выражение:
journalctl -n1 --output=json |
jq '(.__REALTIME_TIMESTAMP | tonumber/1000000 | strftime("%Y-%m-%d %H:%M:%S")), .MESSAGE'
Это выражение выполняет следующую последовательность действий:
journalctl -n1 --output=json
: Запрашивает последнюю запись журнала в формате JSON..__REALTIME_TIMESTAMP | tonumber/1000000
: Находит ключ__REALTIME_TIMESTAMP
, преобразует его значение из строки в число и делит его на 1000000 для получения секунд.strftime("%Y-%m-%d %H:%M:%S")
: Форматирует полученное числовое значение времени в читаемый для человека формат даты и времени (YYYY-MM-DD HH:MM:SS
)..MESSAGE
: Извлекает сообщение из журнала для отображения.
Применение
Таким образом, для корректного отображения временной метки и сообщения необходимо соблюдать синтаксис jq
и последовательность преобразований. Пример выше показывает один из возможных путей решения задачи. Стоит обратить внимание на детализацию временной метки с миллисекундами, что может быть выполнено с использованием дополнительных функций и методов обработки, как показано в следующем примере:
journalctl -axf --output=json |
jq -r '[
(.__REALTIME_TIMESTAMP | tonumber/1000000 | strftime("%F %T")) + "." +
(.__REALTIME_TIMESTAMP | tonumber % 1000 | tostring | split(".")[1]),
.MESSAGE
] | @tsv'
Здесь ключ __REALTIME_TIMESTAMP
обрабатывается аналогичным образом, но добавляется форматирование для вывода миллисекунд, которые извлекаются с помощью операции получения остатка от деления и дальнейшего преобразования.
Заключение
В заключении, правильная обработка временных меток требует понимания структуры данных, инструментов и команд, используемых для их обработки. В данном контексте, jq
предоставляет мощный функционал для трансформации JSON-данных, что позволяет адаптировать временные метки и делать их читаемыми для конечного пользователя. Этот подход является полезным не только для специалистов по IT, но и для всех, кто взаимодействует с логами и системными данными в своей работе. Важно учитывать нюансы преобразования и соблюдать предложенные шаги для достижения нужного результата.