2

Есть готовый python скрипт, чтобы сильно не заморачиваться с запуском через supervisor я просто добавил в cron задание:

0 12 * * 1 python /pat/to/script.py > /path/to/my.log

Каждый понедельник в 12 часов запускается скрипт и работает какое-то продолжительное время, а в лог записывает информацию только после окончания работы, что не очень удобно, я не могу посмотреть инфо во время выполнения скрипта, подскажите, как правильно логировать процессы запущенные кроном?

  • так исправьте скрипт, чтобы выдавал нужную вам информацию в нужное вам время. – aleksandr barakin Apr 27 '17 at 10:17
  • @alexanderbarakin много исправлять придется :) Тогда проще запустить супервизором, надеюсь найти более простой способ и получше познакомится с кроном – Igor Lavrynenko Apr 27 '17 at 10:22
  • не ясно, при чём тут программы cron и supervisor. информацию вам выдаёт ваш скрипт. у него, что, недетерминированное поведение? один раз работает так, другой раз эдак, третий вообще никак? – aleksandr barakin Apr 27 '17 at 10:26
  • В какой-то степени да, он работает по-разному в зависимости от данных, которые он собирает и там нет логирования в самом скрипте, если я запускаю его из терминала - получаю информацию в терминал, запускаю cron'ом и получаю лог только после окончания работы скрипта – Igor Lavrynenko Apr 27 '17 at 10:37
  • что значит «нет логирования»? от какой программы тогда вы «получаете информацию в терминал»? – aleksandr barakin Apr 27 '17 at 10:45
  • В процессе работы скрипта сделайте tail -f /path/to/my.log . Показывает? Возможно, в питоне есть отложенный вывод на консоль, как в perl ($|=1)? – Smithson Apr 27 '17 at 10:48
  • 4
    Сделайте логирование в вашем Python скрипте. Для этого есть модуль logging – Pavel Durmanov Apr 27 '17 at 11:19
  • Сделайте логгирование, как правильно подсказывает @Alban, средствами самого Python. Там есть поддержка классического syslog. Да и там можно наворотить гораздо больше и понятнее, чем в сложном shell. – 0andriy Apr 27 '17 at 19:01
  • @Smithson я смотрю tail -f в том то и дело, файл пуст и запись в него происходит после окончания работы скрипта, т.е. операции происходят последовательно, сначало отработает скрипт, потом запишет в файл, похоже действительно придется добавлять логирование в сам скрипт... – Igor Lavrynenko Apr 28 '17 at 08:57
  • 3
    А если запускать с помощью python -u? – andreymal May 03 '17 at 16:31
  • @AK Вас понял, переусердствовал – Igor Lavrynenko May 18 '17 at 08:42

2 Answers2

3

Я рекомендую лог реализовать внутри скрипта.

Всё очень подробно расписанно в документации

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

import logging
level = logging.DEBUG
FORMAT = '%(asctime)s %(processName)s\%(name)-8s %(levelname)s: %(message)s'
logfile = '/path/to/my.log'
logging.basicConfig(format = FORMAT, level=level, filename = logfile )

logger = logging.getLogger(__name__)
debug = logger.debug
print = logger.info

Тут есть хак с функцией print для python3. Для python2 этот хак реализуется иначе.

import sys
class LoggerWriter:
    def __init__(self, level):
        self.level = level

    def write(self, message):
        if message != '\n':
            self.level(message)

    def flush(self):
        self.level(sys.stderr)

sys.stdout = LoggerWriter(logger.info)
sys.stderr = LoggerWriter(logger.warning)

via

Но вместо хаков лучше переписать принты на logger.info

eri
  • 35,224
2

Вывод перенаправленный в файл является полностью буферизированным (то есть пока не заполнится буфер или явно его не очистить, то в файле вы ничего не увидите). Когда в консоли интерактивно запускается скрипт (стандартный ввод/вывод присоединены к терминалу), буферизация построчная включена.

В cron вы можете просто -u параметр командной строки передать:

</dev/null python -u /path/to/script.py >> /path/to/my.log 2>&1

Сложнее не значит лучше. Вывод из простого print легче забрать чем к примеру редактировать logging настройки скрипта, упакованного в docker-контейнер, внутри него самого. Или даже просто, если вы интерактивно хотите скрипт запустить, то каждый раз лезть в него тоже не очень удобно. logging это уровень абстракции, который позволяет разделить: какие события регистрировать (с акцентом на относительной важности разных событий в коде, генерируемых иерархией loggers), от того кто эти события потребляет (handlers) и как они форматируются (formatters). Если logging используете, то удобно добавить возможность читать конфигурацию, которая задаёт loggers, handlers, formatters из файла.

jfs
  • 52,361