使用 macOS 安装环境,见到过很数种环境变量配置方法,每次也都是按照别人的代码,人家配置在哪 我就配置在哪,其实不太清楚有什么区别,决定记录下。
- 本机 macOS 13.3,从 macOS Catalina(10.15) 开始,macOS的默认终端从bash变成了zsh ,所以在网上经常看到的
~/.bash_profile
事实上是无法生效的,应该修改~/.zshrc
。 - 我们常说的环境变量修改有两种方式,分为系统级别(对所有用户生效)和用户级别(对当前用户生效),像
/etc/profile
这种在 /etc 目录下的配置则都属于全局配置,~/
则属于用户级别的,当然 macOS 也不是服务器,一般就自己一个人用,也不用分得太清楚。
系统级别
/etc/profile
文件- 语法格式:采用 Shell 命令语法
- 加载时间:系统启动时加载,更新重启生效。
- 不建议修改,最好在用户级别的配置文件中进行个性化设置。
/etc/paths
文件:路径格式,在系统启动时,这些路径会被添加到全局的$PATH环境变量的前面,影响所有用户和进程。- 语法格式:每行一个路径,没有特定的语法格式。
- 加载时间:系统启动时加载,更新重启生效【但本机实测更新后,打开新终端窗口能够生效,不确定】。
- 加载原理:系统启动时,其中的路径会被添加到系统的 $PATH 环境变量的前面
- 全局环境变量建议修改这个文件。
- macOS 特供(
/etc/paths.d/
同),在 Linux 系统中通常不是标准配置,Linux 通常使用/etc/profile
或/etc/environment
/etc/paths.d/
目录:这个目录中可以放置其他路径设置的文件,每个文件包含一行一个路径。同样在系统启动时,这些路径会被添加到全局的$PATH环境变量的前面,影响所有用户和进程。- 语法格式:每个文件包含一组路径,没有特定的语法格式。
- 加载时间:系统启动时加载。
- 加载原理:
/etc/profile
脚本中有一行eval `/usr/libexec/path_helper -s
,这个path_helper
工具会读取/etc/paths.d
目录下的文件里面的路径,然后加载在环境变量$PTAH
。
/etc/paths
vs /etc/paths.d
:
-
macOS 系统升级时,
/etc/paths
文件在系统升级时可能会被覆盖或修改【不过事实上,我一年多以前配的路径现在还活的好好的,中间经历过一次大版本,数次小版本更新】,导致用户的自定义路径设置丢失,而/etc/paths.d/
目录下的路径配置通常不会受到影响。 -
模块化:如果一个软件需要将自己的可执行文件路径添加到全局$PATH中,它可以在/etc/paths.d/目录下创建一个独立的文件,这样具有更高的可维护性,当需要安装、卸载一个软件相关的路径时,系统只需要创建、删除一个单独的文件,整个路径配置也更加清晰易懂。
用户级别
~/.bash_profile
、~/.bash_login
、~/.profile
- zsh 下不生效,如果想让其生效,可以修改
~/.zshrc
,在其中添加如:source ~/.bash_profile
- 语法格式:采用 Shell 命令语法
- 加载时间:用户登录时加载,根据存在的文件依次执行,优先级为
~/.bash_profile > ~/.bash_login > ~/.profile
。 - 加载原理:在用户登录时按顺序查找,按照从前往后的顺序读取,找到第一个存在的文件并执行其中的命令(后面的几个文件就会被忽略了)
是否建议修改:建议在这些文件中进行个性化的环境设置,因为它们只对当前用户有效。 - 建议在这个文件中设置用户级别的自定义配置,它只影响当前用户的非登录 shell 环境
- zsh 下不生效,如果想让其生效,可以修改
注意:与 Bash 不同,Zsh 并没有类似于 Bash 中的 ~/.bash_profile
配置文件。在 Zsh 中,登录时的配置任务主要集中在 ~/.zprofile
文件中。(还有 .zlogin
.zshenv
但是我本机中并没有这些文件)
2. ~/.bashrc
、~/.zshrc
:
- 只在非登录 shell 中读取。它通常用于配置终端的行为和设置用户自定义的环境变量。
- 语法格式:采用 Shell 命令语法
- 加载时间:非登录shell,打开终端窗口时加载。
- 加载原理:
~/.bashrc
文件通常由 Bash 非登录 shell 在启动时加载。它适用于用户的自定义配置,只影响当前终端会话。 - 建议在这个文件中设置用户级别的自定义配置,它只影响当前用户的非登录 shell 环境。
登录 shell 与非登录 shell
登录 shell :在用户登录系统时启动的交互式 shell。当用户通过终端、SSH 或其他方式登录到系统时,登录 shell 会执行用户的登录配置文件,例如 .bash_profile
等(这些文件根据所使用的 shell 类型可能有所不同),登录配置文件通常包含用于设置环境变量、执行启动脚本以及其他需要在登录时进行的操作。
非登录 shell :在已经登录系统的情况下启动的交互式 shell。当用户在登录后打开新的终端窗口或者运行一个 shell 脚本时,会启动一个非登录 shell。非登录 shell 不会读取用户的登录配置文件(所以,修改 ~/.bash_login
后需要 source xx 才能生效),而是读取 ~/.bashrc
或~/.zshrc
等。这些文件通常包含设置别名、定义函数、配置 shell 提示符等。
在使用Windows系统时不会困惑,因为Windows时典型的单用户操作系统,同时只允许一个用户登录,但是在使用macOS后,会比较困惑,到底什么算用户登录?我在图形化界面输入密码后按回车?还是每打开一个终端?困惑的原因也是每次打开终端,都会有类似 login 的字眼。
通过几个例子来明确“用户登录”的概念,什么算“用户登录”,什么算“已经登录”
- 通过命令行登录一个无图形化界面的Linux操作系统:登录 shell,没什么疑问。
- 通过 SSH 远程连接云服务器:登录 shell。通过 SSH 远程登录到服务器时,会启动登录 shell,并执行你的登录配置文件,以确保你获得正确的环境和配置。
- 先通过 SSH 远程连接一次云服务器,同时连接第二次:每个 SSH 连接都会启动一个新的登录 shell,即使你在同一用户下打开多个 SSH 连接,它们也是独立的登录 shell。
- 通过用户登录界面登录图形化界面 Linux 系统:登录 shell,本质上与1相同。
- 通过用户登录界面登录图形化界面 Linux 系统后,再打开一个终端窗口:非登录 shell,不会再次执行登录配置文件,所以为了
~/.bash_login
中的配置能够做到重启终端生效,我们会在.bashrc
或.zshrc
中配置source ~/.bash_profile
。 - 使用 su 命令切换用户:非登录 shell,不会执行目标用户的登录配置文件。
- 执行 shell 脚本:非登录 shell,没什么疑问。
环境变量加载顺序
Mac系统的环境变量,加载顺序为:【这里仅就常见的几种方式做顺序展示,中间过程可能会有一些遗漏】
bash:/etc/profile -> /etc/paths -> /etc/paths.d/ 文件夹所有内容 -> ~/.bash_profile -> ~/.bash_login -> ~/.profile -> ~/.bashrc
zsh:/etc/profile -> /etc/paths -> /etc/paths.d/ 文件夹所有内容 -> ~/.zprofile -> ~/.zshrc
参考资料
-
Mac中环境变量加载顺序 - 宋建明 - 博客园 (cnblogs.com)
-
osx - Use
/etc/paths
or/etc/paths.d
to add items to the PATH in macOS Sierra? - Unix & Linux Stack Exchange