Паспорт генерации изображения
Промт генерации изображения
Dark neon 'underside of progress' scene, cyberpunk workshop mood. A cold teal-cyan progress bar reaches the end and resets, closed into a loop-ring, a groundhog-day recursion; at the loop's center an orphaned warm amber flag-file is stuck, keeping the ring from breaking; cold finished progress versus amber stuck marker. Etched circuit rings, tiny gears and teeth, worn indicator lights, looping flicker, rain-on-glass. Deep shadow, volumetric haze, warm amber and cyan color palette, shallow depth of field, cinematic film still on 35mm, intricately detailed, ultra-detailed, fine textures, rich layered background, ornate mechanical detail, sharp focus, moody atmosphere.
Осиротевший файл-флаг, из-за которого апдейт не исчезает из списка, превращая системные настройки в день сурка.
Домашний сервер на старом Mac mini живёт без монитора и почти без моего внимания: обновления прилетают сами, я захожу раз в неделю глянуть, всё ли живо. Ровно поэтому список обновлений, который упорно не пустеет, я заметил не сразу.
В «Обновлении ПО» висит три версии Command Line Tools: 13.2, 13.4 и 14.2. Нажимаю «Обновить», жду, пока заполнится прогресс-бар. Система рапортует об успехе. Через день открываю настройки снова - и те же три версии снова предлагают себя установке.
Это не похоже на обычный глюк кэша. Обновления не просто «зависли», они проходят весь цикл установки до самого конца, но список обновлений отказывается пустеть.
Ловушка «битого» пакета
Первая версия была очевидной: установка повреждена или срывается в последний момент. Казалось, что пакеты просто не долетают до цели или записываются с ошибкой, из-за чего macOS считает их недоустановленными.
Решил проверить факты, а не полагаться на память или иконку в интерфейсе.
$ pkgutil --pkg-info=com.apple.pkg.CLTools_Executables
package-id: com.apple.pkg.CLTools_Executables
version: 14.2.0.0.1.1668646533
$ xcode-select -p
/Library/Developer/CommandLineTools
$ clang -v
Apple clang version 14.0.0 (clang-1400.0.29.202)
$ ls /Library/Developer/CommandLineTools/SDKs
MacOSX.sdk MacOSX12.3.sdk MacOSX13.sdk
Цифры не врут. CLT 14.2 - потолок для этой версии macOS - физически стоят в системе. Компилятор на месте, SDK развернуты, квитанция об установке (receipt) актуальна. Всё работает.
Полез в логи softwareupdated, надеясь найти там крик о помощи. Нашёл только странные записи: Failed to get battery level (E00002D8). Выглядит как ошибка, но на Mac mini нет батареи. Это просто фоновый шум, который система генерирует по привычке, пытаясь опросить датчики, которых не существует.
Сигнатура бага
Застрял в тупике: все приборы рапортуют «чисто», а интерфейс продолжает кричать, что система не обновлена. В этот момент заметил одну странную деталь. macOS предлагала установить версию 14.2, которая уже была установлена и работала.
Обычно Software Update показывает разницу - то, чего у тебя нет. Здесь же система показывала весь каталог доступных версий. Это была важная улика.
Позвал ИИ, чтобы прогнать через него этот симптом. Вместо того чтобы гадать, напарник предложил проверить конкретный маркер-флаг. Оказалось, что когда Command Line Tools ставятся «headless-путём» - например, через xcode-select --install или когда их дёргает Homebrew при сборке какого-нибудь пакета - GUI-диалог установки может не сработать до конца.
В итоге в системе остаётся «осиротевший» флаг, который сообщает об установке в процессе. Пока этот файл существует, Software Update считает, что прошлая сессия установки не завершена, и переключается из режима «показывать разницу» в режим «показывать всё».
Один лишний файл
Проверка подтвердила диагноз. В папке /tmp обнаружился пустой файл, который и сбивал систему с толку.
$ ls -la /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
-rw-r--r-- 1 root wheel 0 Jul 13 12:46 /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
Ноль байт, права root. Маленький огрызок данных, который заставлял систему бесконечно крутить цикл обновлений. Решение оказалось примитивным - просто удалить этот маркер.
$ sudo rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
$ softwareupdate --list
Software Update Tool
No new software available.
Список мгновенно очистился. Компилятор, SDK и все рабочие инструменты остались нетронутыми. Система наконец-то «увидела», что всё уже стоит на своих местах.
Изнанка маркеров
Эта история про то, как легко обмануться интерфейсу. Мы привыкли доверять прогресс-бару: если он дошёл до конца, значит, задача решена. Но в реальности между «файлы записаны на диск» и «система считает задачу выполненной» лежит тонкий слой служебных файлов-флагов.
Обычно они незаметны и работают штатно. Но стоит одному такому файлу «осиротеть» - остаться после сбоя или некорректного способа установки - и вся логика обновления превращается в фарс.
Интересно, что ИИ здесь сработал не как справочник, а как детектор паттернов. Он распознал специфическую сигнатуру: «предложение уже установленной версии → зависший флаг installondemand». Это напоминание о том, что когда система врёт, нужно искать не там, где «сломано», а там, где хранится информация о том, что считать «сломанным».
Часть темы «Вторая жизнь железа» - там собраны остальные разборы про слабое и старое железо.
