本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2026年06月14日 统计字数: 26380字 阅读时间: 53分钟阅读 本文链接: https://soulteary.com/2026/06/14/rebuild-macos-dev-machine-from-scratch-reproducible-environment-setup.html ----- # 从零重建 macOS 开发机:可复现的环境初始化流程 最近看到同事们在折腾新电脑环境,刚好趁着周末老设备磁盘空间告急(剩余不到 100G),顺手做了一次完整的 macOS 迁移与开发环境重建。 为了节约大家的时间,我尝试把整个过程整理成一套**可复用、可迁移、可重建**的初始化方案。希望能够让后续任何一台新 Mac,都可以在较短时间内恢复为完整开发环境,而不依赖记忆或零散操作。 ## 写在前面 之前也零零碎碎写过一些 macOS 和开发环境配置,但都比较分散,缺乏统一结构。 这一次的目标是把 macOS 从“可用状态”提升为“开发机状态”,并建立一条完整的标准化路径,包括:基础系统、CLI 工具链、语言环境、SSH / GPG、包管理器、常用开发工具。 你可以当它是“安装软件清单”,但其实本质上应该是:一套简单的开发机环境的工程化重建方法论。 > 一台开发机,本质上是一组可控工具链的组合,而不应该是“手工配置的结果”。 ### 设计原则 整个初始化过程遵循三个核心原则: - **可重建(Rebuildable)**:所有步骤都可以从零执行 - **可迁移(Portable)**:环境可以跨机器复用 - **可验证(Verifiable)**:每一步都有明确验证方式 ### 多语言运行时环境统一(Go / Python / Node / Bun) 本文中涉及了四类工作中常见语言的环境配置。之所以大篇幅展开,是因为开发机真正进入“生产力层”的关键一步是:多语言运行时的版本管理与隔离。 这一层要解决的问题是: - 不同项目依赖不同 Node / Python / Go 版本冲突 - PATH 污染导致命令覆盖 - 全局依赖不可控 - 环境在机器之间无法复现 因此,核心目标也非常明确: > 每一种语言都必须具备“可切换、可回滚、可复现”的能力 当这一部分完成后,开发环境就可以变成一个“可切换系统”: - 每个项目拥有自己的 runtime - 不同版本不会互相污染 - 环境随时可以重建 - 本地开发与 CI/CD 保持一致 好了,接下来的所有步骤,都按照“从零恢复一台开发机”的顺序执行。 ## 系统初始化和开发基础 macOS 初始化的第一步,是把系统变成“可开发状态”。 我们需要完成 `Xcode CLI` 工具的初始化: ```bash xcode-select --install sudo xcodebuild -license accept ``` 当初始化完毕后,`git`、`clang / gcc`、`make / ld` 这些后续所有工具链的基础就完备了。 ## HomeBrew Homebrew 是 macOS 上最核心的开源包管理工具之一(项目地址[Homebrew/brew](https://github.com/Homebrew/brew)),基于 BSD-2-Clause 协议。在[HomeBrew 官网](https://brew.sh/),我们能够找到它的安装命令: ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` 如果网络较慢,可以考虑使用镜像源(比如:[HomeBrew 阿里源](https://developer.aliyun.com/mirror/homebrew/)和 [HomeBrew 清华源](https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/)),或者设置当前环境对一次性代理: ```bash export https_proxy=http://127.0.0.1:1234 ``` 执行后,可以看到完整的安装流程日志: ```bash # /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ==> Checking for `sudo` access (which may request your password)... Password: ==> This script will install: /opt/homebrew/bin/brew /opt/homebrew/share/doc/homebrew ... ... /opt/homebrew /etc/paths.d/homebrew ==> The following new directories will be created: /opt/homebrew/bin /opt/homebrew/etc ... ... /opt/homebrew/Caskroom /opt/homebrew/Frameworks ==> The Xcode Command Line Tools will be installed. Press RETURN/ENTER to continue or any other key to abort: ==> /usr/bin/sudo /usr/bin/install -d -o root -g wheel -m 0755 /opt/homebrew ==> /usr/bin/sudo /bin/mkdir -p /opt/homebrew/bin /opt/homebrew/etc /opt/homebrew/include /opt/homebrew/lib /opt/homebrew/sbin /opt/homebrew/share /opt/homebrew/var /opt/homebrew/opt /opt/homebrew/share/zsh /opt/homebrew/share/zsh/site-functions /opt/homebrew/var/homebrew /opt/homebrew/var/homebrew/linked /opt/homebrew/Cellar /opt/homebrew/Caskroom /opt/homebrew/Frameworks ... ... ==> Searching online for the Command Line Tools ==> /usr/bin/sudo /usr/bin/touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress ==> Installing Command Line Tools for Xcode 26.5-26.5 ==> /usr/bin/sudo /usr/sbin/softwareupdate -i Command\ Line\ Tools\ for\ Xcode\ 26.5-26.5 Software Update Tool Finding available software Downloading Command Line Tools for Xcode 26.5 Downloaded Command Line Tools for Xcode 26.5 Installing Command Line Tools for Xcode 26.5 Done with Command Line Tools for Xcode 26.5 Done. ==> /usr/bin/sudo /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools ==> /usr/bin/sudo /bin/rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress ==> Downloading and installing Homebrew... remote: Enumerating objects: 341218, done. remote: Counting objects: 100% (718/718), done. remote: Compressing objects: 100% (358/358), done. remote: Total 341218 (delta 531), reused 404 (delta 360), pack-reused 340500 (from 6) remote: Enumerating objects: 55, done. remote: Counting objects: 100% (33/33), done. remote: Total 55 (delta 33), reused 33 (delta 33), pack-reused 22 (from 1) ==> /usr/bin/sudo /bin/mkdir -p /etc/paths.d ==> /usr/bin/sudo tee /etc/paths.d/homebrew /opt/homebrew/bin ==> /usr/bin/sudo /usr/sbin/chown root:wheel /etc/paths.d/homebrew ==> /usr/bin/sudo /bin/chmod a+r /etc/paths.d/homebrew ==> Updating Homebrew... ==> Downloading https://ghcr.io/v2/homebrew/core/portable-ruby/blobs/sha256:4ba8d535df01e4bf97e6661c3815796fd77364ea2552606e891659133a76f0e1 ################################################################################################################# 100.0% ==> Pouring portable-ruby-4.0.5_1.arm64_big_sur.bottle.tar.gz ==> Installation successful! ==> Homebrew has enabled anonymous aggregate formulae and cask analytics. Read the analytics documentation (and how to opt-out) here: https://docs.brew.sh/Analytics No analytics data has been sent yet (nor will any be during this install run). ==> Homebrew is run entirely by unpaid volunteers. Please consider donating: https://github.com/Homebrew/brew#donations ==> Next steps: - Run these commands in your terminal to add Homebrew to your PATH: echo >> /Users/soulteary/.zprofile echo 'eval "$(/opt/homebrew/bin/brew shellenv zsh)"' >> /Users/soulteary/.zprofile eval "$(/opt/homebrew/bin/brew shellenv zsh)" - Run brew help to get started - Further documentation: https://docs.brew.sh ``` ### 安装过程说明 执行安装后,会经历几个关键步骤: 首先是“权限检查”: ```bash ==> Checking for `sudo` access ``` Homebrew 会确认当前用户是否具备 sudo 权限。 然后是“目录初始化”,(Apple Silicon 默认安装路径是 `/opt/homebrew`,其他设备是 `/usr/local`): ```bash /opt/homebrew/bin /opt/homebrew/etc /opt/homebrew/Cellar ``` 接着是,“Xcode CLI 自动安装”: ```bash Installing Command Line Tools for Xcode ``` Xcode CLI 提供了`git`、`clang`、`make`、`ld` 等关键命令。 最后是 “Homebrew 核心下载”: ```bash Downloading and installing Homebrew... ``` 完成后,Homebrew 本体就可以开始初始化了。 ### 核心环境变量配置 完成安装之后,我们执行下面的命令,就能够完成 `brew` 命令在系统中的注册了。 ```bash echo >> $HOME/.zprofile echo 'eval "$(/opt/homebrew/bin/brew shellenv zsh)"' >> $HOME/.zprofile eval "$(/opt/homebrew/bin/brew shellenv zsh)" ``` 上面命令执行完毕,执行 `brew` 就能够看到它的“用法提示信息”了: ```bash # brew Example usage: brew search TEXT|/REGEX/ brew info [FORMULA|CASK...] brew install FORMULA|CASK... brew update brew upgrade [FORMULA|CASK...] brew uninstall FORMULA|CASK... brew list [FORMULA|CASK...] Troubleshooting: brew config brew doctor brew install --verbose --debug FORMULA|CASK Contributing: brew create URL [--no-fetch] brew edit [FORMULA|CASK...] Further help: brew commands brew help [COMMAND] man brew https://docs.brew.sh ``` 如果输出了类似上面的 `help` 信息,则安装成功。 ## Oh My Zsh Zsh 已经是 macOS 默认 shell,而 Oh My Zsh 是最流行的增强框架。这十年里,虽然有很多 Shell 方案,但如果说在开源软件中找一个最简单、用户量可能最多的方案,莫过于 [ohmyzsh/ohmyzsh](https://github.com/ohmyzsh/ohmyzsh) 了。 安装命令也一样很简单,一行命令: ```bash sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" ``` 命令执行后,等待命令执行完毕: ```bash # sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" Cloning Oh My Zsh... remote: Enumerating objects: 1534, done. remote: Counting objects: 100% (1534/1534), done. remote: Compressing objects: 100% (1446/1446), done. remote: Total 1534 (delta 85), reused 1411 (delta 58), pack-reused 0 (from 0) Receiving objects: 100% (1534/1534), 3.33 MiB | 7.16 MiB/s, done. Resolving deltas: 100% (85/85), done. From https://github.com/ohmyzsh/ohmyzsh * [new branch] copilot/fix-broken-theme-jonathan -> origin/copilot/fix-broken-theme-jonathan * [new branch] master -> origin/master * [new branch] rr-13813-introduce-cooldown-feature -> origin/rr-13813-introduce-cooldown-feature branch 'master' set up to track 'origin/master'. Switched to a new branch 'master' /Users/soulteary Looking for an existing zsh config... Using the Oh My Zsh template file and adding it to /Users/soulteary/.zshrc. __ __ ____ / /_ ____ ___ __ __ ____ _____/ /_ / __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \ / /_/ / / / / / / / / / / /_/ / / /_(__ ) / / / \____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/ /____/ ....is now installed! Before you scream Oh My Zsh! look over the `.zshrc` file to select plugins, themes, and options. • Follow us on X: https://x.com/ohmyzsh • Join our Discord community: https://discord.gg/ohmyzsh • Get stickers, t-shirts, coffee mugs and more: https://commitgoods.com/collections/oh-my-zsh ``` 执行后会自动完成:`~/.oh-my-zsh` 目录等创建,并创建`~/.zshrc`,确认将默认 shell 切换为 `zsh`,并初始化 git 插件支持。 ### 安装自动补全插件 如果说有哪些插件是 Oh My Zsh 必备,体验提升最大的,自动补全绝对是之一。当我们完成本体的安装后,先执行命令,完成自动补全功能的的插件下载: ```bash git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions ``` 等待命令执行完毕: ```bash # git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions Cloning into '/Users/soulteary/.oh-my-zsh/custom/plugins/zsh-autosuggestions'... remote: Enumerating objects: 2591, done. remote: Counting objects: 100% (150/150), done. remote: Compressing objects: 100% (64/64), done. remote: Total 2591 (delta 124), reused 86 (delta 86), pack-reused 2441 (from 3) Receiving objects: 100% (2591/2591), 596.14 KiB | 1.87 MiB/s, done. Resolving deltas: 100% (1656/1656), done. ``` 接着,我们编辑 `.zshrc` 配置,把自动补全功能激活。 末日配置中的内容是: ```bash plugins=(git) ``` 我们将它修改为下面的内容,然后保存文件。 ```bash plugins=( git zsh-autosuggestions ) ``` 重新打开终端,上面的内容就都会生效了。 之后,我们在终端里输入命令的时,如果遇到了我们之前输入过的内容,便会提醒我们完整命令。 首先是,基于历史命令提示。当我们输入命令时会自动补全: ```bash git c ``` 会提示: ```bash git commit ``` 会出现基于历史记录的预测: ```bash docker compose u ``` 可能会直接提示: ```bash docker compose up -d ``` 这样子,重复输入的很多内容的成本就被一次次的输入命令的过程中被减少了。 ## GPG 与 RSA Key 的使用(Git 签名体系) 在开发过程中,我们通常使用 `git` 进行代码管理。为了确保提交内容的真实性与不可伪造性,可以使用 GPG 签名机制对 commit 和 tag 进行加密签名验证。 但其实,在现代开发环境中,身份体系通常是分裂的: - SSH:用于远程访问(Git / Server) - GPG:用于签名(Commit / Tag) - Git:只是调用外部工具 但如果不做统一设计,会出现三个问题:key 管理混乱、agent 多套冲突、commit / SSH 身份不一致。 ### 整体签名体系结构 现代 Git + GPG 的签名流程如下: ```bash # Git → GPG → gpg-agent → pinentry-mac Git ├── commit/tag signing → GPG ├── SSH authentication → ssh-agent └── identity unification → gpg-agent (optional bridge) ``` 这四个部分,分别负责: - `Git`:触发签名请求 - `GPG`:执行签名/验证逻辑 - `gpg-agent`:管理密钥与缓存 - `pinentry-mac`:负责 macOS 图形化密码输入 在 macOS 环境中,我们可以使用 gpg-agent 作为主 agent,并托管 SSH。 ### 安装 GPG 环境 使用我们刚刚安装好的 Homebrew,安装必要组件: ```bash # gnupg:GPG 主程序 # pinentry-mac:macOS 图形密码输入器 brew install gnupg pinentry-mac ``` 执行命令后,耐心等待: ```bash # brew install gnupg pinentry-mac ✔︎ JSON API packages.arm64_tahoe.jws.json Downloaded 15.2MB/ 15.2MB ==> Would install 2 formulae: gnupg pinentry-mac ==> Downloading https://ghcr.io/v2/homebrew/core/gnupg/manifests/2.5.20 ################################################################################################################# 100.0% ==> Would install 17 dependencies for gnupg: ca-certificates gmp libunistring gettext ... ou can now set this as your pinentry program like ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-mac ==> Summary 🍺 /opt/homebrew/Cellar/pinentry-mac/1.3.1.1: 20 files, 556KB ==> Running `brew cleanup pinentry-mac`... ==> Caveats ==> pinentry-mac You can now set this as your pinentry program like ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-mac ``` 安装完成后,Homebrew 会提示 pinentry 的使用方式,例如: ```bash You can now set this as your pinentry program like ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-mac ``` 我们有更好的方式。 ### 初始化 GPG 配置 创建 GPG 配置目录并设置权限: ```bash mkdir -p ~/.gnupg ``` 写入 `gpg-agent` 配置: ```bash cat < ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-mac enable-ssh-support EOF ``` 设置文件和目录正确的权限: ```bash find ~/.gnupg -type d -exec chmod 700 {} \; find ~/.gnupg -type f -exec chmod 600 {} \; ``` ### 配置 shell 环境(zsh) 接着,我们在 `.zshrc` 中添加配置: ```bash # GPG export GPG_TTY=$(tty) # 让 pinentry 使用 macOS GUI,避免卡输入 export PINENTRY_USER_DATA="USE_TTY=1" # 在 shell 中启动 agent gpgconf --launch gpg-agent # SSH 通过 gpg-agent 统一管理 export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) ``` ### SSH Key 管理 当上面的信息完成后,我们可以使用 `ssh-add` 来添加我们的 RSA Key。(SSH Key 与 GPG Key 是两套体系,这里仅作为扩展说明) ```bash ssh-add ~/.ssh/key-1 ssh-add ~/.ssh/key-2 ``` 使用 `ssh-add -l` 可以查看 Key 的加载情况: ```bash ssh-add -l ``` 根据我们添加的 Key 的实际情况,可能可以看到类似下面的内容: ```bash 3072 SHA256:123456+123456 key-1 (RSA) 2048 SHA256:234567/345678+1234/123 key-2 (RSA) ``` ### 导入 GPG Key 导入已有 key: ```bash gpg --import ~/mykey.asc ``` 根据导入的 key 的情况,可能得到类似下面的结果: ```bash gpg: /Users/soulteary/.gnupg/trustdb.gpg:建立了信任度数据库 gpg: 密钥 DBCDD8CBF440F8DE:公钥 “Su Yang ” 已导入 gpg: 密钥 DBCDD8CBF440F8DE:私钥已导入 gpg: 处理的总数:1 gpg: 已导入:1 gpg: 读取的私钥:1 gpg: 导入的私钥:1 ``` ### 检查 GPG Key 状态 接下来,我们可以使用命令检查导入的 Key 的信息: ```bash gpg --list-secret-keys --keyid-format LONG ``` 输出示例: ```bash /Users/soulteary/.gnupg/pubring.kbx ----------------------------------- sec rsa4096/DBCDD8CBF440F8DE 2023-10-11 [SC] CD85ED7465AFF2FFA2FFB686DBCDD8CBF440F8DE uid [ 未知 ] Su Yang ``` `sec` 表示该 key 具备可用于签名的私钥,在使用的时候,我们通常使用 `rsa4096/...` 后面的短 key ID,而最下面的一长串 fingerprint 是这个 Key 的唯一标识 key。 ### 导出公钥(用于 GitHub / Gitea 等平台) 我们也可以通过命令,查询公钥,将公钥内容绑定到想要使用的系统平台里: ```bash gpg --armor --export DBCDD8CBF440F8DE ``` 输出结果类似: ```bash -BEGIN PGP PUBLIC KEY BLOCK----- mQINBGUmIH0BEAC6/bQb7Tb8nvLJhmJSnFfeAPahLlYtN462q7ukvbUi8LShhEK4 G1qAnQDgNedfH4Jn77DNGpHaPFaEjNvtqP76q0/Q33iV9MV6dfZMMy2txIoKny3f PQJwSidmRCC0Hl0ntKUqEyyTgbAirLYKZ132c5NCp+AEk9J/07Ig1igAOMoFaAxK B2/ ... wKESEp25n0CiBrBMtDWgQVR3OO10X0oI5nuSM2gh1PxN7LFALyXu IZd9qjg+wN9wD81x1bFCnTJbQ7dILi5ukJzf36X1Q6VqT8XTbEs3V/ZDWICCSfqJ fpK6Q1kCbrUl++6kE4tTCca1amMvGTZFa6xpeBMKxgLncXBa9N/F8pppqX5PiLhX 8rs+DBsOTB0yKwYnquCYymW4Wjv5BPMYf35tm0s1OGNDRtZczQFjKX0gMVtz5+1+ 9pzZ =etbA -----END PGP PUBLIC KEY BLOCK----- ``` ### 配置 Git 使用 GPG 签名 想要使用 GPG 签名,我们首先要进行 Git 的基础设置: ```bash git config --global user.name "Your Name" git config --global user.email "you@example.com" ``` 然后,开启签名功能: ```bash git config --global commit.gpgsign true git config --global tag.gpgsign true git config --global gpg.program gpg git config --global gpg.format openpgp ``` 最后,设置签名 key: ```bash # git config --global user.signingkey git config --global user.signingkey DBCDD8CBF440F8DE ``` 因为不同的GPG 版本下fingerprint(`CD85ED7...`)解析可能有差异,所以建议我们使用短 ID (`DBCDD8CB...`) 。 ### 创建测试仓库验证签名 让我们来验证上面的配置是否正确: ```bash # 创建一个测试目录,并切换工作目录 mkdir git-commit-test cd git-commit-test # 初始化 git 仓库 git init # 随便创建一个文件 touch abc # 将刚刚的文件添加到待提交列表里 git add . ``` 然后,使用 `git commit -S` 进行带签名的记录提交: ```bash git commit -S -m "test signed commit" ``` 执行成功,输出示例: ```bash [main (root-commit) 0070f81] test signed commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 abc ``` ### 验证签名是否正确 提交完毕,可以使用 `git log` 来检查是否正确进行签名: ```bash git log --show-signature -1 ``` 输出示例: ```bash commit 0070f8104cf00f42fb86bf5bc9dbd935c147a494 (HEAD -> main) gpg: 签名建立于 日 6月/14 17:31:40 2026 CST gpg: 使用 RSA 密钥 CD85ED7465AFF2FFA2FFB686DBCDD8CBF440F8DE gpg: 完好的签名,来自于 “Su Yang ” [未知] gpg: 警告:此密钥未被受信任签名认证! gpg: 没有证据表明此签名属于其声称的所有者。 CD85ED7465AFF2FFA2FFB686DBCDD8CBF440F8DE Author: Su Yang Date: Sun Jun 14 17:31:40 2026 +0800 test signed commit ``` 从上面的日志中,我们可以看到签名是有效的:“完整的签名”,没有“篡改”提醒。信息中的警告是因为本机尚未建立对该 GPG key 的信任链,不是签名错误。 ### 常见问题 这里将常见问题也进行总结,应该能够节约很多折腾的同学的时间。 最常见的问题是,因为gpg-agent 未正确加载,pinentry 可能不弹窗。解决方法是重新启动 `agent` 程序: ```bash gpgconf --kill gpg-agent gpgconf --launch gpg-agent ``` 然后,可能出现的问题是:`git` 找不到 `gpg`。我们可以使用命令来定位程序: ```bash which gpg ``` 确保在 `/opt/homebrew/bin/gpg` 路径中有程序,或目录被加入到了可被 shell 检索到的环境变量中。 ## Go 环境(GVM) 我之前曾写过几篇相关的内容:《[搭建可维护的 Golang 开发环境](https://soulteary.com/2022/07/04/build-a-maintainable-golang-development-environment.html)》、《[M1 芯片 Mac 上更好的 Golang 使用方案](https://soulteary.com/2022/05/12/better-golang-usage-on-m1-mac.html)》、《[Golang 多版本管理](https://soulteary.com/2021/12/15/golang-multi-version-management.html)》。 这几年用下来,个人体感,还是在 2022 年,我做过修正的 GVM 版本最好用。项目开源地址是:[soulteary/gvm](https://github.com/soulteary/gvm)。Go 的配置和使用,我们有三个核心原则,不污染系统环境、每个版本独立安装,GO PROXY 单独设置。 安装很简单,也是一条命令: ```bash curl -sSL https://github.com/soulteary/gvm/raw/master/binscripts/gvm-installer | bash ``` 安装成功能够看到下面的日志: ```bash Cloning from https://github.com/soulteary/gvm.git to /Users/soulteary/.gvm No existing Go versions detected Installed GVM v1.0.24 Please restart your terminal session or to get started right away run `source /Users/soulteary/.gvm/scripts/gvm` ``` 我们在 `~/.zshrc` 中添加下面的配置: ```bash # Golang & GVM export GOPROXY="https://goproxy.cn" export GO_BINARY_BASE_URL=https://golang.google.cn/dl/ [[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm" export GOROOT_BOOTSTRAP=$GOROOT ``` 然后重新打开终端,就能够在环境中使用 `gvm` 命令了: ```bash # gvm Usage: gvm [command] Description: GVM is the Go Version Manager Commands: version - print the gvm version number get - gets the latest code (for debugging) use - select a go version to use (--default to set permanently) diff - view changes to Go root help - display this usage text implode - completely remove gvm install - install go versions uninstall - uninstall go versions cross - install go cross compilers linkthis - link this directory into GOPATH list - list installed go versions listall - list available versions alias - manage go version aliases pkgset - manage go packages sets pkgenv - edit the environment for a package set ``` ### 安装和使用指定 Golang 版本 如果我们想使用 `gvm` 来安装最新版本的 `go` 程序,可以先通过 `gvm listall` 来获取官方所有发行版: ```bash # gvm listall gvm gos (available) go1 go1.0.1 go1.0.2 ... go1.26.0 go1.26.1 go1.26.2 go1.26.3 go1.26.4 ... ``` 在列表中找到当前最新的版本,比如 `go1.26.4`,然后使用 `gvm install` 命令,搭配 `-B` 参数,快速下载官方预构建好的版本: ```bash # gvm install go1.26.4 -B Installing go1.26.4 from binary source ``` 完成下载后,我们使用 `gvm use` 命令,配合 `--default` 参数,完成默认版本的设置: ```bash gvm use go1.26.4 --default Now using version go1.26.4 ``` 上面的命令执行完毕后,我们就可以正常使用 `go` 命令了,比如使用 `go version` 查看下我们安装的 `go` 运行时是否正确: ```bash # go version go version go1.26.4 darwin/arm64 ``` ## Python 环境 Python 的使用,我们设置三个原则: 1. 不使用系统 Python 2. 不使用 `pip global install` 3. 所有依赖必须在 `env` 中隔离 这里推荐使用 `Miniforge`,基于 BSD-3 协议的轻量 Conda 分发版。开源项目地址:[conda-forge/miniforge](https://github.com/conda-forge/miniforge)。 我们通过一条命令完成工具的下载: ```bash curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ``` 安装文件不大,大概 50MB 左右: ```bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 100 50.9M 100 50.9M 0 0 10.4M 0 0:00:04 0:00:04 --:--:-- 17.0M ``` 然后使用 `bash` 命令搭配 `-b` 参数完成安装: ```bash bash Miniforge3-$(uname)-$(uname -m).sh -b ``` 等待命令执行完毕: ```bash # bash Miniforge3-$(uname)-$(uname -m).sh -b PREFIX=/Users/soulteary/miniforge3 Unpacking bootstrapper... Unpacking payload... Extracting bzip2-1.0.8-hd037594_9.conda Extracting c-ares-1.34.6-hc919400_0.conda Extracting ca-certificates-2026.5.20-hbd8a1cb_0.conda Extracting libcxx-22.1.6-h55c6f16_0.conda Extracting libev-4.33-h93a5062_2.conda Extracting libexpat-2.8.1-hf6b4638_0.conda Extracting libffi-3.5.2-hcf2aa1b_0.conda Extracting libiconv-1.18-h23cfdf5_2.conda Extracting liblzma-5.8.3-h8088a28_0.conda Extracting libmpdec-4.0.0-h84a0fba_1.conda Extracting libzlib-1.3.2-h8088a28_2.conda ... Installing base environment... Transaction Prefix: /Users/soulteary/miniforge3 Updating specs: - bzip2==1.0.8=hd037594_9 - c-ares==1.34.6=hc919400_0 - ca-certificates==2026.5.20=hbd8a1cb_0 - libcxx==22.1.6=h55c6f16_0 - libev==4.33=h93a5062_2 - libexpat==2.8.1=hf6b4638_0 ... - conda-package-handling==2.4.0=pyh7900ff3_2 - conda==26.3.2=py313h8f79df9_1 Package Version Build Channel Size ───────────────────────────────────────────────────────────────────────────────────── Install: ───────────────────────────────────────────────────────────────────────────────────── + archspec 0.2.5 pyhd8ed1ab_0 conda-forge + backports.zstd 1.5.0 py313h7208f8c_0 conda-forge + boltons 25.0.0 pyhd8ed1ab_0 conda-forge + brotli-python 1.2.0 py313hde1f3bb_1 conda-forge + bzip2 1.0.8 hd037594_9 conda-forge + c-ares 1.34.6 hc919400_0 conda-forge ... + zstandard 0.25.0 py313h9734d34_1 conda-forge + zstd 1.5.7 hbf9d68e_6 conda-forge Summary: Install: 80 packages Total download: 0 B ───────────────────────────────────────────────────────────────────────────────────── Transaction starting Linking bzip2-1.0.8-hd037594_9 Linking c-ares-1.34.6-hc919400_0 Linking ca-certificates-2026.5.20-hbd8a1cb_0 ... Linking requests-2.34.2-pyhcf101f3_0 Linking conda-libmamba-solver-26.4.2-pyhd8ed1ab_0 Linking conda-package-handling-2.4.0-pyh7900ff3_2 Linking conda-26.3.2-py313h8f79df9_1 Transaction finished ``` 在完成安装之后,我们将下面的配置添加到 `~/.zshrc` 中: ```bash # Python [ -f "$HOME/miniforge3/etc/profile.d/conda.sh" ] && \. "$HOME/miniforge3/etc/profile.d/conda.sh" export PATH="$HOME/miniforge3/bin:$PATH" ``` 我们执行 `~/miniforge3/bin/conda init`完成项目的第一次初始化: ```bash # ~/miniforge3/bin/conda init no change /Users/soulteary/miniforge3/condabin/conda no change /Users/soulteary/miniforge3/bin/conda no change /Users/soulteary/miniforge3/bin/activate no change /Users/soulteary/miniforge3/bin/deactivate no change /Users/soulteary/miniforge3/etc/profile.d/conda.sh no change /Users/soulteary/miniforge3/etc/fish/conf.d/conda.fish no change /Users/soulteary/miniforge3/shell/condabin/Conda.psm1 no change /Users/soulteary/miniforge3/shell/condabin/conda-hook.ps1 no change /Users/soulteary/miniforge3/lib/python3.13/site-packages/xontrib/conda.xsh no change /Users/soulteary/miniforge3/etc/profile.d/conda.csh modified /Users/soulteary/.bash_profile ==> For changes to take effect, close and re-open your current shell. <== ``` 重新打开终端后,我们就能够正常使用熟悉的 `conda` 命令啦。 ```bash # conda usage: conda [-h] [-v] [--no-plugins] [-V] COMMAND ... conda is a tool for managing and deploying applications, environments and packages. options: -h, --help Show this help message and exit. -v, --verbose Can be used multiple times. Once for detailed output, twice for INFO logging, thrice for DEBUG logging, four times for TRACE logging. --no-plugins Disable all plugins that are not built into conda. -V, --version Show the conda version number and exit. commands: The following built-in and plugins subcommands are available. COMMAND activate Activate a conda environment. check Display a health report for your environment (alias for doctor). clean Remove unused packages and caches. commands List all available conda subcommands (including those from plugins). Generally only used by tab-completion. compare Compare packages between conda environments. config Modify configuration values in .condarc. create Create a new conda environment from a list of specified packages. deactivate Deactivate the current active conda environment. doctor Display a health report for your environment. env Create and manage conda environments. export Export a given environment info Display information about current conda install. init Initialize conda for shell interaction. install Install a list of packages into a specified conda environment. list List installed packages in a conda environment. menuinst A subcommand for installing and removing shortcuts via menuinst. notices Retrieve latest channel notifications. package Create low-level conda packages. (EXPERIMENTAL) remove (uninstall) Remove a list of packages from a specified conda environment. rename Rename an existing environment. repoquery Advanced search for repodata. run Run an executable in a conda environment. search Search for packages and display associated information using the MatchSpec format. update (upgrade) Update conda packages to the latest compatible version. ``` ### 验证和使用 过去有一些文章提到过 `conda` 命令的使用,如果你感兴趣可以翻阅:《[在搭载 M1 及 M2 芯片 MacBook设备上玩 Stable Diffusion 模型](https://soulteary.com/2022/12/10/play-the-stable-diffusion-model-on-macbook-devices-with-m1-and-m2-chips.html)》、《[用让新海诚本人惊讶的 AI 模型制作属于你的动漫视频](https://soulteary.com/2022/06/04/create-your-own-anime-video-with-an-ai-model-that-surprised-makoto-shinkai.html)》、《[向量数据库入坑指南:聊聊来自元宇宙大厂 Meta 的相似度检索技术 Faiss](https://soulteary.com/2022/09/03/vector-database-guide-talk-about-the-similarity-retrieval-technology-from-metaverse-big-company-faiss.html)》。 ## Node.js 环境 我们使用开源项目 `nvm` 来管理 Node.js 版本:[nvm-sh/nvm](https://github.com/nvm-sh/nvm)。过去的十年里,这个项目非常稳定,在许多互联网公司里也承担过各种 CI 构建过程中的顶梁柱的角色。 关于 Node.js 环境同样约定三个原则: 1. 不使用系统环境中的 Node(包括 `brew` 安装的) 2. 所有版本由 `nvm` 控制 3. `npm` 全局安装仅用于 CLI 工具 同样是一句命令完成安装: ```bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash ``` 耐心等待完成安装: ```bash #curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 17051 100 17051 0 0 25641 0 --:--:-- --:--:-- --:--:-- 25640 => Downloading nvm from git to '/Users/soulteary/.nvm' => Cloning into '/Users/soulteary/.nvm'... remote: Enumerating objects: 432, done. remote: Counting objects: 100% (432/432), done. remote: Compressing objects: 100% (359/359), done. remote: Total 432 (delta 61), reused 192 (delta 45), pack-reused 0 (from 0) Receiving objects: 100% (432/432), 418.80 KiB | 1.12 MiB/s, done. Resolving deltas: 100% (61/61), done. * (HEAD detached at FETCH_HEAD) master => Compressing and cleaning up git repository => Appending nvm source string to /Users/soulteary/.zshrc => Appending bash_completion source string to /Users/soulteary/.zshrc => Close and reopen your terminal to start using nvm or run the following to use it now: export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion ``` 上面的日志提醒我们要在 `~/.zshrc` 中添加配置信息,其实在执行完毕后,`nvm` 会帮助我们自动添加一部分内容: ```bash # Node.js export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion ``` 我们可以手动额外添加一句配置,让后续的使用更丝滑: ```bash # 额外添加,加速下载 export NVM_NODEJS_ORG_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/nodejs-release/ ``` ### 安装和使用 当我们完成 `nvm` 的安装后,可以使用 `nvm ls-remote` 命令,来获取所有的 Node 可用版本: ```bash # nvm ls-remote v0.1.14 v0.1.15 v0.1.16 v0.1.17 ... v22.16.0 (Latest LTS: Jod) ... v24.1.0 ``` 这里我们以安装最新的 LTS 版本(列表中的 `v22.6.0`)为例。 使用 `install` 命令,搭配具体版本号: ```bash # nvm install v22.16.0 Downloading and installing node v22.16.0... Downloading https://mirrors.tuna.tsinghua.edu.cn/nodejs-release//v22.16.0/node-v22.16.0-darwin-arm64.tar.xz... ################################################################################################################# 100.0% Computing checksum with sha256sum Checksums matched! Now using node v22.16.0 (npm v10.9.2) Creating default alias: default -> v22.16.0 * ``` 如果你只有一个版本,程序会自动帮助你将这个版本设置为全局默认版本。但当你如果下载了更多的版本,想进行版本切换的时候,需要牢记下面的两个命令: ```bash # nvm use 22.16.0 Now using node v22.16.0 (npm v10.9.2) # nvm alias default 22.16.0 default -> 22.16.0 (-> v22.16.0) ``` 想要切换全局版本,首先要使用 `nvm use` 切换具体版本,然后要使用 `nvm alias default` 来变更全局默认版本。 命令执行完毕后,我们可以检查 Node 版本是否符合预期: ```bash # node -v v22.16.0 ``` ## Bun(更现代的 JS Runtime) 作为更现代的 JS Runtime,[Bun](https://bun.com/) 提供了四个主要能力:runtime、package manager、bundler、test runner。 我们还是可以通过一行命令,完成安装: ```bash curl -fsSL https://bun.sh/install | bash ``` 安装速度通常非常快: ```bash ######################################################################## 100.0% bun was installed successfully to ~/.bun/bin/bun Added "~/.bun/bin" to $PATH in "~/.zshrc" To get started, run: exec /bin/zsh bun --help ``` 完成安装之后,我们同样在 `~/.zshrc` 中添加配置: ```bash # bun completions [ -s "/Users/soulteary/.bun/_bun" ] && source "/Users/soulteary/.bun/_bun" # bun export BUN_INSTALL="$HOME/.bun" export PATH="$BUN_INSTALL/bin:$PATH" ``` 重新打开终端后,我们就可以使用 `bun` 命令啦: ```bash # bun Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.3.14+0d9b296af) Usage: bun [...flags] [...args] Commands: run ./my-script.ts Execute a file with Bun lint Run a package.json script test Run unit tests with Bun x next Execute a package binary (CLI), installing if needed (bunx) repl Start a REPL session with Bun exec Run a shell script directly with Bun install Install dependencies for a package.json (bun i) add @remix-run/dev Add a dependency to package.json (bun a) remove babel-core Remove a dependency from package.json (bun rm) update @evan/duckdb Update outdated dependencies audit Check installed packages for vulnerabilities outdated Display latest versions of outdated dependencies link [] Register or link a local npm package unlink Unregister a local npm package publish Publish a package to the npm registry patch Prepare a package for patching pm Additional package management utilities info @zarfjs/zarf Display package metadata from the registry why zod Explain why a package is installed build ./a.ts ./b.jsx Bundle TypeScript & JavaScript into a single file init Start an empty Bun project from a built-in template create elysia Create a new project from a template (bun c) upgrade Upgrade to latest version of Bun. feedback ./file1 ./file2 Provide feedback to the Bun team. --help Print help text for command. Learn more about Bun: https://bun.com/docs Join our Discord community: https://bun.com/discord ``` ## 其他:macOS 开发机初始化的其他流程 当在完成系统工具链、Shell、安全体系以及多语言运行时之后,整个开发机其实已经具备了“可用状态”。 不过,通常一台新设备到手,为了使用起来更安心,我通常还会做下面的一些动作: 1. 检查/更新系统版本,确认已经到最新版本。 2. 登录合适的 Apple 账号,完成 iCloud 的必要信息同步。 3. 可能设置一些鼠标、触摸板拖动、手势相关的配置,让每次操作都更省力。 4. 把常用的 macOS 先都打开一遍,让 iCloud 能够完成必要的信息同步,而不是先使用,可能造成数据冲突。 5. 过程中,可以移除掉不用的 Dock 栏软件,让常驻软件图标更顺手,以及为当前设备改个共享名称。 6. 如果你需要更新和同步相册数据,这时可以打开图片软件,挂在后台进行持续更新。 7. 当基础软件信息都同步完毕之后,我们可以开始从 Apple App Store 中下载常用的软件,这类软件通常叫做受限的 MAS 软件,对系统的影响和损害可能性是最低的,因为会被限制在 Apple 沙盒环境中。 8. 接下来,我们需要完成 xcode 软件的下载,以及初始化好 `git` 软件(初始化 xcode 命令行 `sudo xcodebuild -license`)。 9. 当上面的内容都就绪后,我们可以开始下载非 Mac 和App Store 之外的软件了,我通常会完成 Chrome 、Little Snitch、VSCode(Cursor)、Localsend 等软件等安装。 10. 最后就是类似本文的配置,跨设备数据同步,包括微信记录同步等工作啦。 ## 最后 希望看到这里的你的设备,目前的状况已经是一台“可重建的开发系统”啦。 —EOF