Исправление зависшего скрипта онбординга для Mac после обновления Homebrew 6.0
29 de julio de 2026
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Придя утром на работу, я обнаружил десятки сообщений в Slack о том, что скрипт онбординга для новых сотрудников завис. Открыв терминал, я увидел, что процесс бесконечно висит на этапе brew install, ожидая пользовательского ввода.
С выходом Homebrew 6.0 были ужесточены политики интерактивного интерфейса (Ask mode) и блокировки стандартного ввода (stdin). Когда человек вводит команды вручную, проблем не возникает, но при запуске Shell-скрипта в фоновом режиме терминал попадает в состояние взаимной блокировки ввода-вывода (deadlock).
Если постоянные вопросы коллег по настройке окружения рушат ваш рабочий поток, самое время самостоятельно прописать в скрипт несколько переменных окружения и обработку исключений.
В Homebrew 6.0 установка пакетов при отсутствии подключения к TTY (интерактивному терминалу) вызывает неожиданное ожидание ввода-вывода. Чтобы предотвратить зависание терминала и создать полностью автономную среду выполнения, в самом начале скрипта необходимо явно указать специальные переменные окружения.
Добавление следующих переменных в верхнюю часть скрипта отключит все интерактивные запросы и подсказки, кроме запроса прав администратора.
`bash
#!/usr/bin/env zsh
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_ACCEPT_OUTDATED_CAVEATS=1
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "(/usr/local/bin/brew shellenv)"
else
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
safe_brew_install() {
local formula="{formula}" &>/dev/null; then
echo "Уже установлено: {formula}"; then
echo "Ошибка: не удалось установить ${formula}" >&2
return 1
fi
fi
}
safe_brew_install "git"
safe_brew_install "jq"
`
Если вы используете встроенный файл конфигурации brew.env вместо .zshrc, убирайте ключевое слово export и записывайте параметры исключительно в формате пар ключ-значение, например HOMEBREW_NO_ENV_HINTS=1, чтобы избежать синтаксических ошибок.
Начиная с версии 6.0, по соображениям безопасности цепочки поставок по умолчанию применяется «Tap Trust Model». Непроверенные сторонние Custom Tap или старые пакеты, использующие MD5 или SHA-1, просто блокируются при попытке загрузки.
Формулы для распространения внутренних инструментов компании должны обязательно содержать дайджест SHA-256 и проходить проверку brew audit --strict, иначе конвейер CI/CD завершится с ошибкой.
`ruby
class InternalApiCli < Formula
desc "사내 인프라 API 제어 및 배포 자동화 CLI 도구"
homepage "https://internal.company.net/docs/cli"
url "https://internal.company.net/downloads/cli/v2.4.0/internal-api-cli-2.4.0.tar.gz"
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
license "Proprietary"
depends_on "jq"
def install
bin.install "internal-api-cli"
end
test do
assert_match "version 2.4.0", shell_output("#{bin}/internal-api-cli --version")
end
end
`
Пропишите внутри файла Formula для внутреннего использования (internal-api-cli.rb) идентификатор лицензии стандарта SPDX (license "Proprietary"), а также точные поля url и desc. Удобно настроить CI/CD-пайплайн так, чтобы после скачивания файла значение хэша извлекалось через shasum -a 256 и автоматически обновлялось с помощью sed.
На локальных Mac разработчиков достаточно один раз выполнить brew trust company/tools, чтобы добавить внутренний Tap в список доверенных источников — после этого установка будет проходить без предупреждений безопасности.
Если терминал VS Code или старый эмулятор терминала работает как бинарный файл Intel (x86_64), то даже на Mac с чипом M-серии результат выполнения uname -m будет x86_64. Если устанавливать пакеты Homebrew в таком состоянии, x86-бинарники будут помещены в /usr/local, что приведет к ошибке mach-o file, but is an incompatible architecture.
Необходимо условие, которое проверяет, работает ли среда терминала под Rosetta 2, и при необходимости сразу перезапускает процесс в нативном режиме arm64.
`bash
#!/usr/bin/env zsh
SYSTEM_ARCH="(sysctl -n sysctl.proc_translated 2>/dev/null || echo "0")"
if [[ "{SYSTEM_ARCH}" == "x86_64" && "0" "{SYSTEM_ARCH}" == "x86_64" && "${IS_TRANSLATED}" == "0" ]]; then
HOMEBREW_PREFIX="/usr/local"
else
echo "Неподдерживаемая архитектура: ${SYSTEM_ARCH}" >&2
exit 1
fi
eval "{HOMEBREW_PREFIX}/bin/brew shellenv)"
`
Если при запросе параметра ядра sysctl -n sysctl.proc_translated возвращается 1, это означает режим Rosetta 2. Выполнение exec arch -arm64 /bin/zsh "$0" "$@" переключает весь скрипт на командную оболочку arm64, благодаря чему корректные бинарные файлы устанавливаются по пути /opt/homebrew.
Когда у разных разработчиков различаются версии Homebrew и состав установленных пакетов, неизбежно возникает ситуация «на моем компьютере всё работает». Связка декларативного Brewfile и команды brew bundle check в скрипте позволяет новичку настроить всё окружение буквально одной командой.
`bash
#!/usr/bin/env zsh
set -euo pipefail
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_BUNDLE_NO_UPGRADE=1
DOTFILES_REPO="https://github.com/company/dotfiles.git"
TARGET_DIR="$HOME/.dotfiles"
if ! command -v brew &>/dev/null; then
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
if [[ ! -d "{DOTFILES_REPO}" "{TARGET_DIR}" pull origin main
fi
BREWFILE_PATH="{BREWFILE_PATH}" &>/dev/null; then
echo "Все зависимости из Brewfile находятся в актуальном состоянии."
else
brew bundle install --file="${BREWFILE_PATH}"
fi
`
Синхронизируйте корпоративный репозиторий Dotfiles в $HOME/.dotfiles, после чего сначала проверьте наличие недостающих пакетов с помощью brew bundle check. Если запускать brew bundle install только при обнаружении отсутствующих пакетов, скрипт можно выполнять сколько угодно раз, неизменно сохраняя идентичность окружения.