Что такое…

Что такое stdout и stderr — и почему ошибки не попадают в твой лог-файл

Иллюстрация: из одной машины выходят две трубы — широкая с ровным потоком и узкая, из которой капают красные капли

Смотри, загадка. Ты запускаешь python bot.py > log.txt, чтобы весь вывод ушёл в файл. Программа падает. Ошибка красуется прямо на экране. Открываешь log.txt — а там только обычные сообщения, никакой ошибки.

Файл не сломан, и > не сломан. Просто у каждой программы не один выход, а два. Ты перенаправил только один.

Два выхода у каждой программы

Когда программа что-то печатает, она выбирает, в какую «трубу» писать:

  • stdout (standard output, стандартный вывод) — обычный результат работы.
  • stderr (standard error, вывод ошибок) — ошибки, предупреждения, служебные сообщения.

По умолчанию обе трубы выведены на экран терминала. Поэтому ты их не различаешь — текст просто идёт подряд.

Зачем две? Чтобы результат и проблемы не смешивались. Представь кухню: готовые блюда идут через окно раздачи, а жалобы — через отдельную дверь. Если отправить блюда на банкет, жалобы всё равно придут к тебе, а не гостям.

Кто куда пишет:

  • print() в Python и console.log() в Node — в stdout.
  • console.error() в Node — в stderr.
  • Модуль logging в Python по умолчанию — в stderr. Да, даже обычные INFO-сообщения.
  • Трейсбек упавшей программы — всегда в stderr.

Как управлять трубами

У труб есть номера: stdout — это 1, stderr — 2. Отсюда весь синтаксис:

python bot.py > out.txt          # только stdout в файл
python bot.py 2> errors.txt      # только stderr в файл
python bot.py > all.txt 2>&1     # обе трубы в один файл
python bot.py 2>/dev/null        # ошибки — в никуда

2>&1 читается как «отправь вторую трубу туда же, куда сейчас идёт первая».

И вот грабли, на которые наступают все. Порядок важен:

python bot.py > all.txt 2>&1     # ✓ обе трубы в файле
python bot.py 2>&1 > all.txt     # ✗ ошибки всё равно на экране

Перенаправления выполняются слева направо. Во втором варианте 2>&1 сработал первым — когда stdout ещё смотрел на экран. Ошибки «прилипли» к экрану. Потом stdout ушёл в файл, а stderr остался. Запомни: сначала файл, потом 2>&1.

А иногда трубы полезно, наоборот, развести по разным файлам:

npm run build > build.log 2> errors.log

Сборка напечатала тысячу строк прогресса, а ошибок три. Открываешь errors.log — и сразу видишь только их, без прокрутки.

Та же логика и с трубой |: она передаёт дальше только stdout. Поэтому npm run build | grep error может ничего не найти — ошибки шли мимо, в stderr.

Почему логи Python в Docker приходят с опозданием

Вторая загадка. Бот в Docker работает, но docker logs пустой. А через пару минут вываливается сразу пачка сообщений.

Дело в буфере. Когда stdout смотрит в терминал, Python отправляет каждую строку сразу. Когда stdout уходит в файл или трубу — как в Docker — Python копит текст и отправляет порциями. Ради скорости.

А stderr не копится никогда. Ошибки приходят мгновенно, а обычные print застряли в буфере. Отсюда странные логи, где ошибка стоит раньше событий, которые к ней привели.

Чинится одним из трёх способов:

python -u bot.py                 # запуск без буфера
ENV PYTHONUNBUFFERED=1           # в Dockerfile — для всего контейнера
print("старт", flush=True)       # для одной строки

Строку с PYTHONUNBUFFERED=1 ты увидишь почти в каждом Dockerfile для Python. Теперь ты знаешь зачем.

Как это помогает в работе с ИИ

Когда ИИ-агент запускает команду, он видит обе трубы и код выхода. Но если ты сам копируешь ему вывод, частая ошибка — скопировать только «чистую» часть. Сохраняй всё: команда > out.txt 2>&1, и отдавай файл целиком. Самое ценное для отладки обычно в stderr: путь к файлу, номер строки, имя упавшей функции. Без этого ИИ гадает, а с этим — чинит с первого раза.

А если нужны постоянные логи на сервере — это уже следующий уровень, о нём в статье что такое логи.

Ошибка в stderr значит, что программа упала?

Нет. В stderr пишут и предупреждения, и прогресс — например, npm и git выводят туда много служебного. Упала ли программа, говорит только код выхода.

Есть ли stdout и stderr на Windows?

Да. В PowerShell и cmd работают те же >, 2> и 2>&1. Только вместо /dev/null пишут NUL в cmd или $null в PowerShell.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →