Homebrew долго обновляется: brew update и установка без ожидания
Вы набираете brew install jq, а вместо установки видите ==> Auto-updating Homebrew... и ждёте. Иногда минуту, иногда дольше. Бывает и так, что brew update висит вовсе без вывода. Разберём, что Homebrew делает в этот момент, как найти медленный шаг и какие настройки убирают ожидание, не превращая систему в набор устаревших пакетов.
Что происходит при brew update
С версии 4.0 Homebrew по умолчанию не держит на диске локальные копии больших репозиториев homebrew/core и homebrew/cask. Вместо этого он скачивает JSON-описания формул и кастов с formulae.brew.sh, а с версии 4.1 ещё и проверяет подпись этих файлов. Поэтому обычный brew update сейчас состоит из трёх частей:
- обновление самого Homebrew: это git-репозиторий
Homebrew/brewна GitHub; - загрузка свежих JSON-файлов API, если локальные устарели;
git fetchдля каждого стороннего tap, который вы когда-то подключили черезbrew tap.
Готовые бинарные пакеты (bottles) скачиваются уже при установке, по умолчанию из GitHub Packages, то есть с ghcr.io. Отсюда первое правило диагностики. Если долго идёт обновление, ищите причину в трёх пунктах выше. Если обновление прошло быстро, а тянется установка, смотрите на загрузку bottles или на сборку из исходников.
Найдите медленный шаг
Запустите обновление с подробным выводом:
brew update --verboseФлаг --verbose печатает проверяемые каталоги и выполняемые git-операции, поэтому видно, на каком репозитории всё замирает. Если этого мало, brew update --debug покажет трассировку всех shell-команд. Для загрузок добавьте переменную HOMEBREW_CURL_VERBOSE=1: Homebrew передаст curl флаг --verbose, и вы увидите каждый HTTP-запрос и момент, где соединение остановилось.
Засеките время командой time brew update и запустите её дважды подряд. Второй запуск должен пройти почти мгновенно, потому что обновлять уже нечего. Если и он долгий, дело не в объёме обновлений, а в соединении или в каком-то из tap.
Затем проверьте общее состояние установки:
brew doctor
brew config
brew tapbrew doctor находит типичные проблемы конфигурации, в том числе лишние локальные tap. brew config показывает версию, префикс установки и заданные переменные HOMEBREW_*. brew tap выводит все подключённые tap. Каждый из них при обновлении опрашивается отдельно, и один заброшенный репозиторий способен затормозить всё обновление.
Лишние локальные копии homebrew/core и homebrew/cask
Если Homebrew ставился давно, на диске могли остаться полные клоны homebrew/core и homebrew/cask. При установке через API они не нужны, но занимают место и тоже обновляются. Если вы не разрабатываете формулы, удалите их:
brew untap homebrew/core homebrew/caskФормулы и касты продолжат ставиться через API. Заодно пройдитесь по выводу brew tap: если какой-то сторонний tap давно не нужен, brew untap владелец/репозиторий уберёт одну git-операцию из каждого обновления.
Отдельно проверьте, не задана ли у вас переменная HOMEBREW_NO_INSTALL_FROM_API. Она возвращает старое поведение: Homebrew работает с локальными git-копиями homebrew/core и homebrew/cask, которые обновляются заметно дольше. Кроме того, с этой переменной интервал автообновления по умолчанию сокращается до пяти минут. Включать её стоит только для разработки формул.
Автообновление перед install
Перед brew install, brew upgrade и brew tap Homebrew сам запускает обновление, если с прошлого прошло достаточно времени. По умолчанию это 24 часа, а если вы запускали команды для разработчиков, интервал сокращается до часа. Поведение настраивается переменными окружения:
| Переменная | Что делает |
|---|---|
| HOMEBREW_NO_AUTO_UPDATE=1 | полностью отключает автообновление перед командами |
| HOMEBREW_AUTO_UPDATE_SECS=604800 | запускает автообновление не чаще раза в неделю, значение в секундах |
| HOMEBREW_API_AUTO_UPDATE_SECS | задаёт, как часто проверять свежесть данных API, по умолчанию 450 секунд |
| HOMEBREW_NO_ENV_HINTS=1 | убирает из вывода подсказки про эти переменные |
Добавьте выбранный вариант в ~/.zshrc или ~/.bashrc:
export HOMEBREW_AUTO_UPDATE_SECS=604800
export HOMEBREW_NO_ENV_HINTS=1Полное отключение удобно в скриптах и CI, где важна предсказуемость. На рабочей машине разумнее увеличить интервал: с выключенным автообновлением легко забыть про brew update и месяцами ставить старые версии. Для разового запуска профиль править не нужно: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq.
Ни одна из этих переменных не мешает обновляться вручную. Удобная привычка: отключить автообновление и раз в неделю, когда есть время подождать, запускать brew update, затем brew outdated, чтобы увидеть устаревшие пакеты, и brew upgrade. Так ожидание переезжает из момента, когда вам срочно нужен пакет, в момент, который вы выбрали сами. На Linux все перечисленные переменные работают так же.
Bottles и сборка из исходников
Иногда медленно идёт не обновление, а сама установка. Если в выводе мелькают ./configure, make или cmake, Homebrew собирает пакет из исходников вместо загрузки готового bottle. Так бывает в трёх случаях:
- Для вашей версии macOS или архитектуры bottle не опубликован. Homebrew прекратил сборку новых bottles для Intel-маков, поэтому на них компиляция встречается всё чаще.
- Homebrew установлен в нестандартный каталог. Стандартные префиксы:
/opt/homebrewна Apple Silicon,/usr/localна Intel,/home/linuxbrew/.linuxbrewна Linux. - Вы сами попросили сборку флагом
--build-from-sourceили ставите версию--HEAD.
Проверить, есть ли готовый пакет, можно через brew info <формула>: в строке с версией будет пометка (bottled). Текущий префикс показывает brew --prefix. Если компиляция происходит из-за нестандартного каталога, надёжнее один раз переустановить Homebrew в стандартный, чем каждый раз ждать сборки. Для сборки из исходников нужны Command Line Tools, их ставит команда xcode-select --install.
Медленные загрузки и обрывы
Если bottles и JSON-файлы скачиваются медленно или загрузка обрывается на середине, помогут настройки curl, через который Homebrew качает файлы:
HOMEBREW_CURL_RETRIESзадаёт число повторов, которое передаётся вcurl --retry. По умолчанию 3, на нестабильной сети поставьте 5 или больше.HOMEBREW_DOWNLOAD_CONCURRENCYуправляет параллельными загрузками. В свежих версиях по умолчанию стоитauto: соединений вдвое больше, чем ядер процессора. Если роутер или прокси плохо переносят много одновременных соединений, поставьте1, и файлы будут качаться по очереди.brew fetch <формула>заранее скачивает bottle или исходники в кэш. Удобно, когда хорошее соединение есть сейчас, а установка понадобится позже.
После установки Homebrew по умолчанию запускает очистку, в выводе появляется строка с brew cleanup. Раз в 30 дней очистка полная и может занять заметное время. Если эта пауза мешает, переменная HOMEBREW_NO_INSTALL_CLEANUP=1 отключает автоматическую очистку. Тогда запускайте brew cleanup вручную, когда удобно.
Кэш и место на диске
Скачанные bottles и исходники лежат в кэше. Посмотреть путь и размер:
brew --cache
du -sh "$(brew --cache)"Очистка:
brew cleanup -n # показать, что будет удалено
brew cleanup # удалить старые версии и устаревшие файлы кэша
brew cleanup --prune=all # удалить все файлы кэшаПри обычной очистке Homebrew удаляет загрузки старых версий и файлы кэша старше 120 дней, этот срок задаёт HOMEBREW_CLEANUP_MAX_AGE_DAYS. Свежие загрузки актуальных версий остаются, поэтому повторная установка того же пакета пройдёт без нового скачивания. Полную очистку с --prune=all делайте, когда действительно нужно место.
Зеркала: HOMEBREW_API_DOMAIN и HOMEBREW_BOTTLE_DOMAIN
Homebrew умеет брать данные с зеркал. Для этого в официальной документации описаны четыре переменные:
| Переменная | Что заменяет | По умолчанию |
|---|---|---|
| HOMEBREW_API_DOMAIN | JSON API с описаниями формул и кастов | https://formulae.brew.sh/api |
| HOMEBREW_BOTTLE_DOMAIN | загрузку bottles и их манифестов | https://ghcr.io/v2/homebrew/core |
| HOMEBREW_BREW_GIT_REMOTE | git-репозиторий самого Homebrew | https://github.com/Homebrew/brew |
| HOMEBREW_CORE_GIT_REMOTE | git-репозиторий homebrew/core | https://github.com/Homebrew/homebrew-core |
Если нужного файла на зеркале API или bottles временно нет, Homebrew берёт его с основного адреса. Сами зеркала поддерживают сторонние организации, обычно университеты и хостинги, и у каждого своя инструкция с точными адресами. Копируйте значения оттуда, а не из случайных форумов.
Помните о доверии. Документация Homebrew прямо предупреждает, что зеркалу git-репозиториев вы доверяете так же, как самому Homebrew. Подключайте только зеркала, в которых уверены, и убирайте переменные, когда зеркало перестало быть нужным: отставшее или медленное зеркало само становится причиной задержек.
Если --verbose показывает, что время уходит на соединение с github.com, formulae.brew.sh или ghcr.io, а не на работу самого Homebrew, дело в маршруте до этих серверов. Здесь помогает защищённое подключение через ближайшую к ним локацию.
Коротко
- Найдите медленный шаг:
brew update --verbose, затемbrew doctorиbrew tap. - Удалите ненужные локальные копии командой
brew untap homebrew/core homebrew/cask, если не разрабатываете формулы. - Не держите включённой
HOMEBREW_NO_INSTALL_FROM_APIбез причины. - Задайте
HOMEBREW_AUTO_UPDATE_SECS=604800, а в CI используйтеHOMEBREW_NO_AUTO_UPDATE=1. - Если идёт компиляция, проверьте пометку
(bottled)вbrew infoи префикс черезbrew --prefix. - На нестабильной сети увеличьте
HOMEBREW_CURL_RETRIES, при сбоях параллельной загрузки поставьтеHOMEBREW_DOWNLOAD_CONCURRENCY=1. - Зеркала подключайте только проверенные и только через документированные переменные.
- Кэш смотрите командой
brew --cache, чистите черезbrew cleanup.