إصلاح سكربت الإعداد الأولي على Mac المتوقف بسبب تحديث Homebrew 6.0
2026년 7월 29일
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
وصلتُ إلى العمل هذا الصباح لأجد عشرات الرسائل المتراكمة على Slack تفيد بتوقف سكربت الإعداد الأولي (Onboarding) للموظفين الجدد. وعند فتح الطرفية (Terminal)، تبين أن السكربت يتوقف تماماً أثناء تنفيذ أمر brew install بانتظار إدخال من المستخدم.
مع الترقية إلى Homebrew 6.0، تم تعزيز سياسات الواجهة التفاعلية (Ask mode) وحظر الإدخال القياسي (stdin). لا توجد مشكلة عندما يدخل الإنسان الأوامر يدوياً، ولكن عند تشغيل السكربت في الخلفية عبر Shell، تدخل الطرفية في حالة جمود (Deadlock) بين الإدخال والإخراج.
إذا كانت استفسارات أفراد الفريق حول تهيئة بيئاتهم تُعطل تدفق عملك الشخصي، فقد حان الوقت لإدراج بعض المتغيرات البيئية ومعالجة الاستثناءات مباشرة داخل السكربت.
يتسبب Homebrew 6.0 في انتظار غير متوقع للإدخال/الإخراج عند تثبيت الحزم بدون اتصال TTY (الطرفية التفاعلية). ولمنع ظاهرة الانتظار هذه وإنشاء بيئة تنفيذ آلية ومستقلة تماماً، يجب التصريح بمتغيرات بيئية مخصصة في أعلى السكربت.
إضافة المتغيرات التالية في أعلى السكربت ستؤدي إلى إيقاف جميع الموجهات التفاعلية وعرض التلميحات، باستثناء طلبات صلاحة المدير (Sudo).
`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"
`
عند استخدام ملف إعدادات Homebrew المدمج brew.env بدلاً من ملف .zshrc، يجب حذف الكلمة المفتاحية export وكتابة المتغيرات على شكل أزواج مفتاح-قيمة مثل HOMEBREW_NO_ENV_HINTS=1 فقط لتجنب أخطاء بناء الجملة (Syntax error).
بدءاً من الإصدار 6.0، يتم تطبيق "Tap Trust Model" بشكل افتراضي لدواعي أمان سلسلة التوريد (Supply chain security). وبالتالي، يُحظر تحميل الـ Custom Taps الخارجية غير الموثوقة أو الحزم القديمة التي تستخدم MD5 أو SHA-1.
يجب أن تتضمن الـ Formula المخصصة لتوزيع أدوات الشركة الداخلية معرّف 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
`
قم بتضمين معرّف الترخيص وفق معايير SPDX (license "Proprietary") وحقول url و desc الدقيقة داخل ملف الـ Formula الخاص بالتوزيع الداخلي (internal-api-cli.rb). ومن المريح أتمتة هذه العملية بتوليد القيمة عبر shasum -a 256 بعد تنزيل الملف في خط أنابيب CI/CD وتحديثها تلقائياً باستخدام sed.
وعلى أجهزة Mac المحلية الخاصة بالمطورين، يتيح تشغيل الأمر brew trust company/tools مرة واحدة تسجيل الـ Tap الخاص بالشركة كمصدر موثوق، مما يسمح بالتثبيت المباشر دون تحذيرات أمنية.
إذا كانت طرفية VS Code أو محاكي الطرفية القديم يعمل كملف تنفيذي مخصص لـ Intel (x86_64)، فستكون نتيجة uname -m هي x86_64 حتى لو كنت تستخدم جهاز Mac بمعالج من سلسلة M. وفي هذه الحالة، سيؤدي تثبيت حزم 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" "$@" السكربت بالكامل إلى غلاف (shell) بمعمارية arm64، مما يضمن تثبيت الملفات التنفيذية الصحيحة في المسار /opt/homebrew.
إذا كانت إصدارات Homebrew والحزم المثبتة تختلف من مطور لآخر، فستتكرر مشكلة "الأمر يعمل على جهازي!". يوفر دمج ملف Brewfile الخصائصي (declarative) مع الأمر 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 فقط عند وجود حزم مفقودة، ستضمن الحفاظ على بيئة متطابقة بغض النظر عن عدد مرات تكرار تشغيل السكربت.