Число «640 ТБ в год» — настоящее. А вот вывод «это гарантированно убьёт ваш SSD меньше чем за год» — самая слабая и наименее точная часть всей истории. По-настоящему тревожно здесь другое — то, что этот баг вскрывает. Подсистема локального хранения Codex относится к вашему диску как к свалке, и злополучный лог-приёмник уровня TRACE — лишь один из доброго десятка способов, которыми один и тот же код тихо стачивает флеш-память, вешает десктоп-клиент, корёжит собственные базы данных, а в худших задокументированных случаях — удаляет пользовательские файлы. Давайте разберёмся, что там реально творится, где вирусный заголовок передёргивает и почему чинить это надо не на уровне «отключить логи».
🔥 Что реально происходит под капотом
Разработчик под ником 1996fanrui (issue #28224) описал картину, от которой холодеет любой, кто бережёт железо. После примерно 21 дня аптайма его системный SSD принял на запись около 37 ТБ. Покопавшись на уровне процессов и файлов, он нашёл главного виновника — базу диагностических логов Codex (~/.codex/logs_2.sqlite и её спутники -wal и -shm). В пересчёте на год это даёт те самые ~640 ТБ.
Самое коварное — что по размеру самой базы вы ничего не заметите. На диске лежит чуть больше гигабайта логов (около 1 035 МиБ, ~682 тысячи строк), и это число почти не растёт. Фокус в том, что Codex пишет в режиме «вставил → проиндексировал → сбросил в WAL → удалил». Автор замерил: за 15 секунд в базу прилетело 36 211 новых строк, при том что количество хранимых строк осталось ровно прежним. То есть на диске вечный гигабайт, а под капотом — конвейер, перемалывающий данные с амплитудой, которой хватило бы на серверную СУБД под нагрузкой.
Откуда столько? Разбивка по уровням логирования говорит сама за себя:
📈 TRACE — 70,7% всех байт. Это уровень детализации, который в проде вообще не включают.
📈 INFO — 25,7%, и почти всё это зеркальные события телеметрии OpenTelemetry (codex_otel.log_only и codex_otel.trace_safe).
📈 DEBUG и WARN — жалкие 3,6% на двоих, то есть всё хоть сколько-нибудь осмысленное.
А вот что именно сидит в этом TRACE — отдельный анекдот. Крупнейший источник (527 МиБ из гигабайта!) — это codex_api::endpoint::responses_websocket, то есть сырые тела websocket/SSE-ответов модели, которые приложение зачем-то складывает на диск целиком. Второй по «вкладу» — банальный спам файловых событий inotify: система десятки тысяч раз пишет в лог, что кто-то ОТКРЫЛ ld.so.cache, locale.alias, passwd или nsswitch.conf. В дампе автора одно только событие открытия ld.so.cache встречается 128 764 раза. Это не диагностика — это цифровой шум, который не нужен ни пользователю, ни самим разработчикам Codex.
⚙️ Одна строчка на Rust, которая всё ломает
Корень проблемы — обезоруживающе простой. Лог-приёмник, который пишет в SQLite, инициализируется с глобальным фильтром по умолчанию:
Targets::new().with_default(Level::TRACE)
Эта строчка означает буквально следующее: сохранять на диск всё, от всех модулей, на максимальном уровне детализации — включая внутренности сетевых библиотек (hyper_util, tokio-tungstenite), низкоуровневую возню OpenTelemetry SDK и те самые сырые протокольные пейлоады. Никакой фильтрации по умолчанию просто нет.
Отдельно стоит развеять недопонимание из вирусного пересказа: переменная RUST_LOG тут действительно ни при чём — но не потому, что Codex её «полностью игнорирует» из вредности. В соседнем issue #17320 разработчик показал тонкость: расширение корректно выставляет процессу RUST_LOG=warn (это видно в /proc/<pid>/environ), но SQLite-приёмник логов живёт в обход стандартного механизма фильтрации RUST_LOG и тащит на диск TRACE несмотря ни на что. Это не «забыли прочитать переменную», а архитектурное решение: у диагностического стока свой захардкоженный фильтр, перекрывающий всё, что вы пытаетесь настроить снаружи.
Дальше — механика WAL (write-ahead log), которая и создаёт ту самую амплитуду. SQLite в режиме WAL сначала дописывает каждое изменение в отдельный файл журнала, и при потоковой генерации событий этот logs_2.sqlite-wal распухает на глазах. В том же #17320 зафиксированы скорости записи ~5 МиБ/с в среднем и до ~16 МиБ/с в пике во время стриминга ответа модели — для текстовых-то логов это абсурд. А когда автор того issue просто перенаправил базу в tmpfs, дисковый ввод-вывод от расширения упал до нуля. Это окончательно доказало: весь поток — чистый побочный эффект логирования, а не полезная работа.
💾 Реальность ресурса SSD: где заголовок передёргивает
А теперь главная поправка, ради которой стоило всё это разбирать. Тезис «640 ТБ в год = 640 полных перезаписей терабайтного диска = гарантированная смерть накопителя с ресурсом 600 TBW меньше чем за год» арифметически верен, но по сути вводит в заблуждение.
Дело в том, что TBW (Terabytes Written) — это не порог смерти, а граница гарантии. Производитель обязуется, что до этой цифры диск точно отработает; что будет после — отдельный вопрос, и ответ на него обычно куда оптимистичнее. Современные контроллеры используют выравнивание износа (wear leveling) и резерв ячеек (over-provisioning), а независимые «пытки на убой» не раз показывали, что потребительские SSD переживают кратно больше заявленного TBW, прежде чем реально посыпаться. Так что превышение 600 TBW за год означает не «диск умрёт», а «гарантия аннулирована, и вы вошли в зону, за которую вендор не ручается». Риск растёт — да. «Гарантированно убьёт» — нет.
Но именно поэтому история не становится менее скандальной — она становится более скандальной. Потому что:
🗑️ Каждый из этих 640 ТБ — мусор. Это не ваши данные, не история переписки, не индексы — это сырые websocket-пейлоады и спам inotify, которые удаляются через секунду после записи.
🗑️ Вы платите ресурсом железа за телеметрию, которой даже не пользуетесь. Контроллер диска ещё и добавляет свою амплитуду записи поверх — так что реальный износ NAND выше «честных» 640 ТБ.
🗑️ На дешёвых TLC/QLC-накопителях с низким ресурсом P/E-циклов эта нагрузка ощутимо приближает деградацию, даже если до «кирпича» далеко.
Иными словами, паниковать про «год до смерти диска» не надо. Возмущаться тем, что платный инструмент жжёт чужой ресурс записи на пустом месте, — надо.
🧩 Почему это симптом, а не болезнь
Если бы дело было в одной строчке Level::TRACE, я бы не называл это архитектурной проблемой. Но загляните в список связанных issue — и складывается портрет системы, которая в принципе не умеет аккуратно обращаться с локальным диском:
⚠️ Десктоп-клиент намертво не запускается, когда logs_2.sqlite распухает: пул соединений SQLite не успевает инициализироваться за отведённый таймаут (#27741).
⚠️ Зависшие и «подвешенные» процессы Codex держат открытым уже удалённый WAL-файл, и тот растёт без границ, отъедая десятки гигабайт (#22444).
⚠️ На длинных активных тредах десктоп становится неюзабельным из-за той же лавины TRACE-логов и роста памяти (#21134).
⚠️ У режима /goal — своя отдельная база goals_1.sqlite, в которую идёт устойчивая запись ~11 МБ/с на базу размером 4 КБ (#27911). Тот же почерк амплитуды, другой файл.
⚠️ При обновлениях SQLite-база состояния регулярно повреждается так, что приложение не стартует и требует ручного «ремонта» (#23787).
И вот тут — про самую жуткую деталь вирусного пересказа, которую нужно честно поправить. В исходном посте утверждается, что в режиме /goal агент «начинает удалять пользовательские файлы, пытаясь очистить переполненный диск». В первоисточнике (#28224) такого нет, и прямой причинно-следственной связи «лог-баг забил диск → агент пошёл его чистить → снёс ваши файлы» я не нашёл нигде.
Но — и это важно — сама по себе проблема разрушительных удалений у Codex реальна и задокументирована, просто растёт она из другого корня. Есть issue, где агент во время «уборки» снёс ~328 тысяч файлов мимо корзины (#12277); есть случай, где десктоп при сбое архивации удалил содержимое 10+ директорий, включая установленные приложения (#18509); на форуме OpenAI лежит целая ветка с подтверждёнными случаями массового удаления файлов в режиме полного доступа на Windows. Механика там — кривой разбор команд очистки, незакрытые кавычки в rm -rf, сбойная архивация — а вовсе не «диск переполнился логами». То есть пересказ склеил два разных реальных бага в одну страшилку. Честная формулировка такая: и логирование жжёт диск, и Codex умеет сносить файлы — но это два отдельных скелета в шкафу, а не один.
Ещё одну ремарку поправлю: в пересказе сказано, что OpenAI «не приняла патч от сообщества, ограничив права внешних контрибьюторов на пулл-реквесты». На деле репозиторий по-прежнему открыт — PR от сторонних разработчиков спокойно создаются (буквально в эти дни), а в свежих релизах уже едут смежные фиксы по SQLite. Официального фикса именно глобального TRACE-фильтра на момент написания нет, но утверждение про «закрытые права контрибьюторов» источниками не подтверждается.
🛠️ Что делать прямо сейчас
Пока официальной заплатки нет, защитить железо можно за минуту. Логика простая: logs_2.sqlite хранит только внутреннюю диагностику, без истории ваших диалогов, поэтому потерять её при перезагрузке абсолютно не страшно.
🧰 Перенесите базу в оперативку (tmpfs). Остановите клиент, переименуйте файл и подложите симлинк на /tmp:
mv ~/.codex/logs_2.sqlite ~/.codex/logs_2.sqlite.bak
ln -s /tmp/logs_2.sqlite ~/.codex/logs_2.sqlite
После этого вся запись уходит в RAM, а диск выдыхает.
🧰 Либо ограничьте запись на уровне ФС — отдельный раздел или квота под ~/.codex, чтобы потоп не дошёл до системного диска. Это особенно актуально на Linux, где переполненный корень способен утащить за собой и менее очевидные вещи — вплоть до проблем с сессиями и авторизацией при перезагрузке.
🧰 И элементарная гигиена для агентов вообще: не гоняйте Codex в режиме полного доступа на основном рабочем диске, держите его в песочнице или VM, а в AGENTS.md пропишите запрет на деструктивные команды. Это страховка не от логов, а от той самой второй категории багов.
Заключение и прогноз
Самое отрезвляющее в этой истории — насколько тривиален настоящий фикс. Не надо переписывать архитектуру: достаточно убрать глобальный Level::TRACE, отрезать шум зависимостей, перестать складывать сырые пейлоады на диск и добавить глобальный лимит размера базы. Сообщество не просто описало проблему — оно принесло готовое решение на блюдечке. Вопрос исключительно в приоритетах OpenAI.
Но я бы не ждал, что одним патчем всё закроется. Закономерность шире одного файла: Codex системно использует локальный диск как черновик — несколько SQLite-баз, у каждой свои гонки, своя амплитуда, свой способ повредиться или зависнуть. Пока у команды не появится дисциплины ретеншена, ротации и жёстких лимитов записи для всего локального состояния, такие истории будут всплывать снова — просто с другим именем файла в заголовке.
Мой прогноз: точечный фикс по #28224 приедет в ближайших релизах — давление сообщества слишком велико, а правка слишком дешёвая. А вот системная санация локального хранилища (корзина перед удалением, единый бюджет записи, вменяемые таймауты) растянется надолго и будет двигаться ровно настолько, насколько OpenAI считает «гигиену диска» важной на фоне гонки за фичами. Для нас, кто гоняет ИИ-агентов локально, вывод предельно практичный: мониторьте износ SSD, песочьте агентов и не давайте инструменту, который пишет 640 ТБ мусора в год, полный доступ к диску, на котором лежит что-то ценное.
А вы следите за TBW своих накопителей, когда запускаете локальные ИИ-агенты? Подозреваю, после этой истории начнёте.
Источники
🔗 Оригинальный issue, с которого всё началось — Codex SQLite feedback logs can write ~640 TB/year: https://github.com/openai/codex/issues/28224
📄 Лонгрид-первоисточник пересказа: https://telegra.ph/Kak-Codex-ubivaet-vash-SSD-bag-logirovaniya-kotoryj-pishet-640-TB-v-god-06-22 ⚙️ Обход RUST_LOG, скорости записи WAL и приём с tmpfs (#17320): https://github.com/openai/codex/issues/17320
💾 Неограниченный рост WAL из-за зависших процессов (#22444): https://github.com/openai/codex/issues/22444
🖥️ Десктоп не стартует при разросшейся базе — таймаут пула SQLite (#27741): https://github.com/openai/codex/issues/27741
🐌 Десктоп становится неюзабельным на длинных тредах из-за TRACE-логов (#21134): https://github.com/openai/codex/issues/21134
🎯 Амплитуда записи в goals_1.sqlite режима /goal (#27911): https://github.com/openai/codex/issues/27911
🧨 Повреждение SQLite-базы состояния при обновлении (#23787): https://github.com/openai/codex/issues/23787
🗑️ Агент удалил ~328 тысяч файлов во время «уборки» (#12277): https://github.com/openai/codex/issues/12277
🗑️ Десктоп снёс содержимое 10+ директорий при сбое архивации (#18509): https://github.com/openai/codex/issues/18509
💬 Ветка на форуме OpenAI с подтверждёнными случаями потери данных на Windows: https://community.openai.com/t/critical-data-loss-issue-in-codex-app-for-windows-agent-executed-file-deletion-outside-project-directory/1375894