docker -py чтение логов контейнера при зависании генератора - PullRequest
0 голосов
/ 10 июля 2020

Я использую docker -py для чтения журналов контейнера в виде потока. установив флаг stream на True, как указано в документации. По сути, я просматриваю все свои контейнеры и читаю их журналы контейнеров в качестве генератора и записываю их в файл, подобный следующему:

for service in service_names:
    dkg = self.container.logs(service, stream=True)
    with open(path, 'wb') as output_file:
        try:
            while True:
                line = next(dkg).decode("utf-8")
                print('line is: ' + str(line))
                if not line or "\n" not in line:  # none of these work
                    print('Breaking...')
                    break
                output_file.write(str(line.strip()))

        except Exception as exc:                  # nor this
            print('an exception occurred: ' + str(exc))

Однако он читает только первую службу и зависает в конец файла. Он не выходит из l oop и не вызывает исключения (например, исключение StopIteration). Согласно документам, если stream=True он должен вернуть генератор, я распечатал тип генератора, и он отображается как docker.types.daemon.CancellableStream, поэтому не думайте, что он будет следовать традиционному генератору python и исключить исключение, если мы нажмем конец генератора журнала контейнера и вызовите next ().

Как видите, я пытался проверить, является ли eol ложным или содержит новую строку, даже посмотреть, поймает ли он какой-либо тип исключения, но не повезло. Есть другой способ. определить, попадает ли он в конец потока для службы, выйти из while l oop и продолжить запись следующей службы? Я хотел использовать поток, потому что большой объем данных в моей системе не хватало памяти, поэтому я предпочитаю использовать генератор.

1 Ответ

1 голос
/ 10 июля 2020

Проблема в том, что поток на самом деле не останавливается, пока контейнер не остановлен, он просто приостанавливается, ожидая прибытия следующих данных. Чтобы проиллюстрировать это, когда он зависает в первом контейнере, если вы сделаете docker stop в этом контейнере, вы получите исключение StopIteration, и ваш for l oop перейдет в журналы следующего контейнера.

Вы можете указать .logs() не следить за журналами, используя follow = False. Любопытно, что в документации указано, что значение по умолчанию - False, но, похоже, это не так, по крайней мере, не для потоковой передачи.

Я столкнулся с той же проблемой, что и вы, и этот фрагмент кода с использованием follow = False не зависает на логах первого контейнера:

import docker
client = docker.from_env()
container_names = ['container1','container2','container3']
for container_name in container_names:
    dkg = client.containers.get(container_name).logs(stream = True, follow = False)
    try:
      while True:
        line = next(dkg).decode("utf-8")
        print(line)
    except StopIteration:
      print(f'log stream ended for {container_name}')   
...