Есть ли способ заставить журнал журналов показывать журналы из «последнего запуска foo.service»?


16

Я особенно заинтересован в том, чтобы посмотреть на выходные данные сервисов oneshot, которые работают по таймеру. --unitФлаг близко, но это объединяющее все пробеги службы вместе. Самым очевидным способом, которым я могу придумать, является фильтрация по PID, но это заставляет меня беспокоиться о повторном использовании PID / услугах, которые разветвляются, и получение последнего PID довольно неудобно. Есть ли какой-то другой идентификатор, который соответствует одному запуску службы, который я мог бы использовать для фильтрации журналов?

РЕДАКТИРОВАТЬ: Я бы с радостью принял авторитетное «нет», если это реальный ответ.

Ответы:


7

Начиная с systemdверсии 232, у нас есть концепция идентификатора вызова. Каждый раз, когда устройство запускается, оно имеет уникальный 128-битный идентификатор вызова. В отличие от того, MainPIDкоторый может быть переработан или у ActiveEnterTimestampкоторого могут быть проблемы с разрешением, это отказоустойчивый способ получить весь журнал вызова конкретного системного модуля.

Чтобы получить последний идентификатор вызова объекта

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Чтобы получить журнал последнего вызова, скажем openipmi, провалился он или нет, вы можете использовать один вкладыш

$ journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value openipmi.service`
-- Logs begin at Thu 2018-07-26 12:09:57 IDT, end at Mon 2019-07-08 01:32:50 IDT. --
Jun 21 13:03:13 build03.lbits openipmi[1552]:  * Starting ipmi drivers
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...fail!
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...done.

(Обратите внимание, что --valueдоступно с тех пор systemd 230, старше InvocationID)


1
Если кто-то пытается это расследовать: journalctl --user -u UNITFILE -f -o json-prettyможет быть полезным; вы ищете MESSAGEполя в частности. Я обнаружил, что вам также может понадобиться USER_INVOCATION_ID, а также к некоторым сообщениям не привязан идентификатор вызова, поэтому их нельзя отфильтровать с помощью этого механизма. Не уверен, почему, может быть, мои записи неправильно настроены ..
karlicoss

14

Я не уверен, какая временная метка имеет больше смысла, но это работает для меня. Надеюсь, что есть лучший способ работы с метками времени, systemctl showчем в awk - не удалось понять, как управлять форматом меток времени.

unit=foo.service

ts=$(systemctl show -p ActiveEnterTimestamp $unit)

echo $ts
ActiveEnterTimestamp=Fri 2016-11-11 12:30:01 MST

journalctl -u $unit --since "$(echo $ts | awk '{print $2 $3}')"

На всякий случай, если кому-то это понадобится как однострочник: journalctl --since " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | меньше
DimanNe

Вы также можете использовать systemctl show -p ActiveEnterTimestamp --value $unit, так что нет необходимости в дополнительных awk
karlicoss

4

Вы можете использовать флаг загрузки, чтобы получать только журналы из этой загрузки. например

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
Это похоже на то, что я хочу, но не работает в ситуациях, таких как: 1) если машина была перезагружена с момента последнего запуска службы, или 2) если служба запускалась несколько раз с момента последней загрузки.
Джек О'Коннор

Я не уверен, почему это не работает в первом случае. Если он был перезагружен, он также будет перезагружен. Вам просто нужно перейти к этой конкретной загрузке и получить информацию. Что касается второго ... вы правы. Журналы шумов зависят от того, сколько раз служба была перезагружена. Но как только вы обнаружили свой pid службы, вы можете отфильтровать его, используя аргумент _PID = XXX. Шансы на повторное использование одного и того же pid для одного и того же сервиса в одном и том же цикле загрузки ... не знаю ... но почти невозможны.
Николайдис Фотис

Я заинтересован в обработке сервисов, которые не обязательно запускаются при загрузке, либо потому, что они работают по таймеру, либо потому, что это одноразовые команды.
Джек О'Коннор

4

Это может помочь вам:

  • journalctl -u foo.service | хвост -n 2

    или замените 2 ожидаемым количеством строк

  • journalctl -u foo.service --since = ' 2016-04-11 13:00:00 '

Вы также можете объединить их, чтобы сначала получить метку времени последнего запуска, а затем использовать эту метку времени с ключом --since.


Это похоже на обходной путь, подобный подходу PID, но он очень ручной. Если мой сервис работает в течение многих секунд и выплевывает много строк журнала, мне нужно искать первую строку, имеющую начальную временную метку, которая мне нужна. Это не очень хорошо работает в сценарии.
Джек О'Коннор

3

Вы можете использовать фильтры полей с Journalctl. Например

journalctl _PID=1234

Получить список всех доступных полей, используя:

journalctl --fields --unit kubelet

Один доступное поле _PID.

Вы можете получить PID запущенного процесса, используя pidofилиsystemctl show --property MainPID <SERVICE_NAME>

Итак, вот как я могу получить логи текущего процесса Kubernetes Kubelet:

# journalctl --unit kubelet _PID=$(systemctl show --property MainPID kubelet 2>/dev/null | cut -d= -f2) | head

Теперь скажите мне, почему я Kubernetes так трудно установить :-(


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.