У меня есть этот файл журнала, который я часто проверяю, и из-за его формата его довольно легко читать, когда он красиво напечатан. Я хотел бы сделать это в хвосте.
Логи в файле типа:
2019-07-04T09:53:04-07:00 some.package.placeholder.stderr {"log": "The content", "foo": "bar", "baz": "blah"}
2019-07-04T10:15:37-07:00 some.package.placeholder.stderr {"log": "I'm actually", "foo": "bar", "baz": "blah"}
2019-07-04T10:15:37-07:00 some.package.placeholder.stderr {"log": "Interested on", "foo": "bar", "baz": "blah"}
И я хочу сделать что-то похожее на
tail -f myLogFile | grep [...?...] | jq '.log'
Итак, при хвосте я получаю:
The content
I'm actually
Interested on
Или даже:
2019-07-04T09:53:04-07:00 The content
2019-07-04T10:15:37-07:00 I'm actually
2019-07-04T10:15:37-07:00 Interested on
@Cyrus не для этого случая, но метка времени, package.placeholder и фактический json могут быть разделены табуляцией/пробелами

С GNU grep для -o:
$ tail file | grep -o '{[^}]*}' | jq -r '.log'
The content
I'm actually
Interested on
С любым awk:
$ tail file | awk 'sub(/.*{/,"{")' | jq -r '.log'
The content
I'm actually
Interested on
$ tail file | awk '{d=$1} sub(/.*{/,""){$0 = "{\"date\": \""d"\", " $0} 1' | jq -r '.date + " " + .log'
2019-07-04T09:53:04-07:00 The content
2019-07-04T10:15:37-07:00 I'm actually
2019-07-04T10:15:37-07:00 Interested on
Этот последний работает путем слияния поля даты из ввода с json, поэтому jq может просто выбрать и распечатать его с полем журнала.
Предположительно, кто-то также захочет использовать параметр командной строки —unbuffered команды jq?
@peak idk, если честно, я только учусь jq, но вполне вероятно, что вы захотите использовать что-то, чтобы отключить буферизацию, поэтому, если эта опция для этого jq, тогда да, и вы также можете добавить fflush() к команды awk после печати каждой строки или вставьте stdbuf или аналогичный вызов.
Если строки журнала разделены табуляцией, вы можете прочитать строки в необработанном виде и разделить на табуляции. Который вы могли бы затем проанализировать json и отфильтровать по своему вкусу и рекомбинировать по мере необходимости.
$ tail -f myLogFile | jq -Rr 'split("\t") | [.[0], (.[2] | fromjson.log)] | join("\t")'
2019-07-04T09:53:04-07:00 The content
2019-07-04T10:15:37-07:00 I'm actually
2019-07-04T10:15:37-07:00 Interested on
Это выглядело потрясающе, но когда я попробовал это с jq версией 1.6 на cygwin, я просто получил assertion "cb == jq_util_input_next_input_cb" failed: file "/usr/src/ports/jq/jq-1.6-1.x86_64/src/jq-1.6/src/util.c", line 371, function: jq_util_input_get_position Aborted (core dumped)
Хм, я не в состоянии отладить и посмотреть, что вызывает это, но, судя по сообщению, я думаю, это проблема с тем, как хвост проходит по выходным данным. Я попробовал это сам в то время в git bash, и он не работает в режиме реального времени, что, как я полагаю, должно работать.
Я получаю то же сообщение об ошибке только от jq '...' file, что и от tail file | jq. Это может быть просто вещь cygwin, idk. Я только начинаю учиться jq поэтому не использовал его много. Быстрый гугл выдал github.com/stedolan/jq/issues/1588, но не знаю, та же ли это проблема или нет.
Вот вещь, которую я использую, которую можно использовать в канале и с файловыми аргументами:
cat /usr/local/bin/j2t
#!/bin/bash
function usage {
cat <<EOF
Usage:
$0 <json filename>
or
tail -F <json filename> | $0
EOF
}
if (($# == 0)); then
{
sed "s/@\(timestamp\)/\1/" | jq -r '[.timestamp, .pri.facility, .pri.severity, .message] | join("\t")'
} < /dev/stdin
else
if [ -r "$1" ] ; then
sed "s/@\(timestamp\)/\1/" $1 | jq -r '[.timestamp, .pri.facility, .pri.severity, .message] | join("\t")'
else
help
fi
fi
например: (если ваш daemon.log - это json)
j2t /var/log/daemon.log
level: 63, builder: awillia2)
2021-08-14T00:00:06.820642+00:00 daemon INFO Starting Run Clamscan...
2021-08-14T00:00:06.846405+00:00 daemon INFO Started Run Clamscan.
Наверное, стоит переформатировать время, оно длинновато.
Может ли
some.package.placeholder.stderсодержать пробелы?