【保姆级教程】一键自动化部署 macOS 开发环境(支持 Intel/Apple 芯片 & 自动避坑)
1. 背景
对于开发者来说,配置新 Mac 或重置开发环境是一项极其耗时的工作。Homebrew 的各种报错、环境变量的繁琐配置、以及 Docker 与系统组件的冲突往往让人头大。本文分享一个经过加固、兼容 macOS 全版本 Bash、且具备智能汇总报告的自动化脚本。
2. 脚本核心亮点
- 极速安装:自动安装 Homebrew 及其核心开发组件。
- 智能避坑:自动检测 Docker Desktop,防止与 Homebrew 版 Docker 冲突。
- 静默安装:过滤 Homebrew 冗长的下载进度日志,只在屏幕展示关键进度。
- 全版本兼容 :兼容 macOS 自带的 Bash 3.2,解决
declare -A报错问题。 - 可视化总结:执行完成后生成全组件安装状态汇总表。
- 断点记录:自动记录所有操作到本地日志文件。
3. 环境要求
- 系统版本:macOS 10.15 (Catalina) 及以上(支持最新的 macOS 15 Sequoia)。
- 芯片架构:完美适配 Intel 芯片及 Apple Silicon (M1/M2/M3) 芯片。
- 网络环境:建议能够正常访问 GitHub 或已配置镜像源。
4. 详细使用步骤
第一步:创建脚本文件
在终端执行以下命令,创建并编辑脚本:
bash
nano install_dev_env.sh
将下面的脚本代码完整复制并粘贴进去。按下 Ctrl + O 保存,Ctrl + X 退出。
bash
#!/bin/bash
# ==========================================
# macOS 开发环境安装脚本 (Bash 3.2 兼容版)
# ==========================================
# 基础设置
set -u
set -o pipefail
# --- 全局变量 ---
LOG_FILE="$HOME/.dev_env_install.log"
# 汇总报告的临时存储文件,替代关联数组
SUMMARY_FILE="/tmp/dev_env_summary.txt"
LOCK_FILE="/tmp/dev_env_install.lock"
BREW_PREFIX="" # 运行时探测
ARCH=""
# 颜色与格式
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# 初始化汇总文件
: > "$SUMMARY_FILE"
# --- 辅助函数 ---
log_step() {
echo -e "\n${BLUE}${BOLD}[STEP] $1${NC}"
echo "[$(date '+%T')] [STEP] $1" >> "$LOG_FILE"
}
log_info() {
echo -e " ${CYAN}ℹ${NC} $1"
echo "[$(date '+%T')] [INFO] $1" >> "$LOG_FILE"
}
log_success() {
echo -e " ${GREEN}✔${NC} $1"
echo "[$(date '+%T')] [SUCCESS] $1" >> "$LOG_FILE"
}
log_warn() {
echo -e " ${YELLOW}⚠ $1${NC}"
echo "[$(date '+%T')] [WARN] $1" >> "$LOG_FILE"
}
log_error() {
echo -e " ${RED}✖ $1${NC}"
echo "[$(date '+%T')] [ERROR] $1" >> "$LOG_FILE"
}
# 记录状态到文件 (替代关联数组)
# 用法: record_status "组件名" "状态带颜色代码"
record_status() {
echo "$1|$2" >> "$SUMMARY_FILE"
}
# 静默执行命令
run_silent() {
local name="$1"
local cmd="$2"
echo -ne " ${BOLD}➜${NC} 正在处理 $name ... "
if eval "$cmd" >> "$LOG_FILE" 2>&1; then
echo -e "\r ${GREEN}✔${NC} $name 处理完成 "
return 0
else
echo -e "\r ${RED}✖${NC} $name 处理失败 "
log_error "$name 执行出错,最后 10 行日志:"
tail -n 10 "$LOG_FILE" | sed 's/^/ /'
return 1
fi
}
cleanup() {
rm -f "$LOCK_FILE"
# 不删除 SUMMARY_FILE 以便调试,或者你可以取消注释下一行
# rm -f "$SUMMARY_FILE"
}
trap 'cleanup' EXIT
# --- 核心逻辑 ---
check_env() {
log_step "环境预检"
if [ -f "$LOCK_FILE" ]; then
if ps -p "$(cat "$LOCK_FILE")" > /dev/null 2>&1; then
log_error "脚本已在运行中 (PID: $(cat "$LOCK_FILE"))"
exit 1
fi
fi
echo $$ > "$LOCK_FILE"
local ver=$(sw_vers -productVersion)
# 兼容 Bash 3.2 的版本比较逻辑
local ver_check=$(echo "$ver" | awk -F. '{ if ($1 > 10 || ($1 == 10 && $2 >= 15)) print "yes"; else print "no" }')
if [[ "$ver_check" == "no" ]]; then
log_error "macOS 版本过低 ($ver),需要 10.15+"
exit 1
fi
log_info "系统版本: macOS $ver"
local m_arch=$(uname -m)
if [[ "$m_arch" == "arm64" ]]; then
ARCH="arm"
BREW_PREFIX="/opt/homebrew"
else
ARCH="intel"
BREW_PREFIX="/usr/local"
fi
export PATH="$BREW_PREFIX/bin:$PATH"
log_info "硬件架构: $ARCH ($BREW_PREFIX)"
}
install_homebrew() {
log_step "Homebrew 设置"
if command -v brew >/dev/null 2>&1; then
log_success "Homebrew 已安装"
run_silent "更新 Homebrew" "brew update"
else
log_info "正在安装 Homebrew..."
# 注意:这里不能静默,因为 Homebrew 安装脚本可能需要用户输入密码
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [[ "$ARCH" == "arm" ]]; then
eval "$($BREW_PREFIX/bin/brew shellenv)"
fi
fi
}
install_pkg() {
local pkg_name="$1"
local brew_name="$2"
local cmd_check="$3"
# 检查汇总文件是否已包含此组件(简单的重复检查)
if grep -q "^${pkg_name}|" "$SUMMARY_FILE"; then
return
fi
# 1. 检查命令
if command -v "$cmd_check" >/dev/null 2>&1; then
# 尝试获取版本号 (稍微复杂的 sed 适配不同输出)
local raw_ver=$($cmd_check --version 2>&1 | head -n 1)
# 简单的提取逻辑,避免复杂的 awk 报错
record_status "$pkg_name" "${YELLOW}已安装 (本地)${NC}"
log_info "$pkg_name 已存在,跳过安装"
return
fi
# 2. 检查 Brew
if brew list --formula | grep -q "^${brew_name}\$"; then
record_status "$pkg_name" "${YELLOW}已安装 (Brew)${NC}"
log_info "$pkg_name Brew Formula 已存在,跳过"
return
fi
# 3. 安装
if run_silent "安装 $pkg_name" "brew install $brew_name"; then
record_status "$pkg_name" "${GREEN}安装成功${NC}"
else
record_status "$pkg_name" "${RED}安装失败${NC}"
fi
}
handle_docker() {
local pkg_name="Docker"
if [ -d "/Applications/Docker.app" ]; then
record_status "$pkg_name" "${YELLOW}已安装 (Desktop)${NC}"
log_info "检测到 Docker Desktop,跳过"
return
fi
if command -v docker >/dev/null 2>&1; then
record_status "$pkg_name" "${YELLOW}已安装 (CLI)${NC}"
return
fi
install_pkg "Docker" "docker" "docker"
}
process_components() {
log_step "组件安装"
# Bash 3.2 也不支持数组里放复杂字符串当结构体用,我们简单展开调用
# 格式: 显示名称 Formula名称 检测命令
install_pkg "Git" "git" "git"
install_pkg "JDK" "openjdk" "java"
install_pkg "Maven" "maven" "mvn"
install_pkg "Node.js" "node" "node"
install_pkg "Python" "python" "python3"
install_pkg "MySQL" "mysql" "mysql"
install_pkg "Redis" "redis" "redis-server"
handle_docker
}
post_config() {
log_step "后续配置"
if brew list --formula | grep -q "openjdk"; then
local jdk_home="$BREW_PREFIX/opt/openjdk/libexec/openjdk.jdk/Contents/Home"
if ! grep -q "JAVA_HOME" "$HOME/.zshrc"; then
echo "" >> "$HOME/.zshrc"
echo "# Java Config" >> "$HOME/.zshrc"
echo "export JAVA_HOME=\"$jdk_home\"" >> "$HOME/.zshrc"
echo "export PATH=\"\$JAVA_HOME/bin:\$PATH\"" >> "$HOME/.zshrc"
log_success "已配置 JAVA_HOME"
else
log_info "JAVA_HOME 已配置,跳过"
fi
if [ ! -d "/Library/Java/JavaVirtualMachines/openjdk.jdk" ]; then
log_warn "建议手动执行以下命令修复 Java 路径识别:"
echo " sudo ln -sfn $BREW_PREFIX/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk"
fi
fi
}
print_summary() {
echo -e "\n=========================================="
echo -e " 🎉 安装结果汇总报告"
echo -e "=========================================="
printf "%-15s | %s\n" "组件名称" "状态"
echo "------------------------------------------"
# 从文件读取并格式化输出 (Bash 3.2 兼容写法)
while IFS='|' read -r name status || [ -n "$name" ]; do
if [ -n "$name" ]; then
printf "%-15s | %b\n" "$name" "$status"
fi
done < "$SUMMARY_FILE"
echo -e "=========================================="
echo -e "详细日志: ${BOLD}$LOG_FILE${NC}"
echo -e "请执行 ${BOLD}source ~/.zshrc${NC} 使配置生效。"
}
# --- 主程序 ---
main() {
mkdir -p "$(dirname "$LOG_FILE")"
echo "=== Session: $(date) ===" > "$LOG_FILE"
check_env
install_homebrew
process_components
post_config
print_summary
}
main
第二步:授予执行权限
bash
chmod +x install_dev_env.sh
第三步:一键运行
bash
./install_dev_env.sh
脚本会引导你进行环境预检、安装 Homebrew、并逐一安装 Git、JDK、Node.js 等组件。
第四步:激活环境变量
安装完成后,终端会提示你:
bash
source ~/.zshrc
5. 常见问题 (FAQ)
-
Q: 为什么 JDK 安装后系统识别不到?
-
A : 脚本会提示你执行一条
sudo ln -sfn...命令。由于系统安全性限制,软链接需要手动确认。 -
Q: 安装过程中卡在 Homebrew 更新怎么办?
-
A : 脚本具备重试机制,如果网络极差,可以
Ctrl+C中断后重新运行,脚本会自动跳过已安装的部分。
6. 环境还原 (卸载脚本)
如果你需要在一台机器上撤销所有操作(删除 Homebrew、清理环境变量、还原备份),请使用以下还原脚本。
还原脚本代码 (restore_env.sh)
bash
#!/bin/bash
# ==========================================
# macOS 开发环境还原/卸载脚本
# ==========================================
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
echo -e "${RED}警告:此脚本将卸载通过脚本安装的组件并还原配置文件!${NC}"
read -p "确定要继续吗?(y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
# 1. 还原配置文件
echo "正在从备份中还原配置文件..."
BACKUP_DIR="$HOME/.dev_env_backups"
if [ -d "$BACKUP_DIR" ]; then
for cfg in .zshrc .bash_profile .bashrc; do
latest_bak=$(ls -t "$BACKUP_DIR/$cfg.bak."* 2>/dev/null | head -n 1)
if [ -n "$latest_bak" ]; then
cp "$latest_bak" "$HOME/$cfg"
echo -e "${GREEN}已还原 $cfg${NC}"
fi
done
fi
# 2. 卸载通过 Homebrew 安装的组件
if command -v brew >/dev/null 2>&1; then
echo "正在卸载常用组件..."
brew uninstall git openjdk maven node python mysql redis docker --force 2>/dev/null
fi
# 3. 询问是否卸载 Homebrew
read -p "是否彻底卸载 Homebrew?(y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "正在卸载 Homebrew (可能需要输入密码)..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
fi
# 4. 清理临时文件
rm -f /tmp/dev_env_install.lock /tmp/dev_env_summary.txt
echo -e "${GREEN}还原操作完成!请重启终端。${NC}"
还原脚本使用说明
- 创建文件:
nano restore_env.sh并粘贴上述代码。 - 授权:
chmod +x restore_env.sh。 - 执行:
./restore_env.sh。
7. 结语
通过自动化脚本,原本需要 1-2 小时的环境配置工作现在只需几分钟,且大大降低了手动配置出错的概率。如果你在 macOS 15.7.3 或其他版本上使用遇到问题,欢迎在评论区交流。