一直以来,配置环境变量的时候都是管中窥豹,对于环境变量的配置似懂非懂。
现在就来认真补一补这方面的不足。
主要内容包括:
-
HOME
- 为什么需要 $,直接打印 HOME 不行吗?
- 一个系统下只有一个 HOME 变量吗?
- 如何 override 系统自定义的 HOME 变量?
- 可以在 bash 中直接通过 $HOME 访问目录吗?
- = 左右有空格吗?
- 如何设置重写的 HOME 永久有效?
-
PATH
- macOS 中如何让.bash_profile 中的 shell 命令永久有效
- 原来似曾相识的这些 bin 存放在这里
-
DIY Variable
- 设置自定义变量
- 读取自定义变量
- shell 间共享自定义变量
- 查看所有的共享变量
先来思考这些问题:
- java,node,go,python bash 环境变量如何设置?
- mysql,mongoDB bash 环境变量如何设置?
- flutter 镜像加速环境变量 PUB_HOSTED_URL,FLUTTER_STORAGE_BASE_URL 如何配置?
- bash variable 和 shell variable 的区别是什么?
专项学习环境变量之前的理解:雾里看花
java,node,go,python 这些命令在 SDK 安装过程中就会自动安装。
mysql,mongoDB bash 环境变量需要手动添加到环境当中。
flutter shell 环境变量需要手动配置。
bash variable 与 shell variable 最直观的区别在于:bash variable 在 bash terminal 中访问;shell variable 在 shell 文件中保存。
专项学习环境变量之后的理解:洞若观火
发现环境变量竟然包括以上如此多内容,最初的问题也可以一一找到答案。
接下来就来看看关于环境变量,到底有哪些需要掌握的知识点。
HOME
这是一个指向用户的 home 目录的 bash var。
格式为 /Users/<username>
或/var/root
(macOS)。linux 系统上为/home/<username>
。
// frank 用户
echo $HOME // /Users/frank
// root 用户
echo $HOME // /var/root
引申问题:
为什么需要 $,直接打印 HOME 不行吗?
在 bash 中,只有加上 $ 以后,系统才会知道我们要输出的是变量,否则会当做输出一个普通字符串处理。
一个系统下只有一个 HOME 变量吗?
取决于系统上有几个用户,有个用户就有几个 HOME 变量。
一般会有一个 root 用户和至少一个普通用户。
如何 override 系统自定义的 HOME 变量?
在~/.bash_profile 中重写。(需要手动 source 才有效,当前 session 有效)
在 bash session terminal 中 export HOME=/Users/frank/foo。(当前 session 有效)
关闭再打开或者新开一个 tab,$HOME 都会变为最原始的值。
不建议重写。具体原因看原因 6。
可以在 bash 中直接通过 $HOME 访问目录吗?
可以。$HOME/tools // /Users/frank/tools
= 左右有空格吗?
没有。空格在 shell 中有特殊含义。
如何设置重写的 HOME 永久有效?
/etc/profile //# System-wide .profile for sh(1)
因为大量的程序依赖 HOME 这个环境变量,所以覆盖系统默认变量是很危险的。
所以一般仅在当前 session 有效,若想永久覆盖,可参考 PATH 的加粗部分。
PATH
这个系统变量,会列出可执行程序的目录。
java,node,go,python 这些命令在 SDK 安装过程中就会自动安装的原因就是这个,sdk 会自动添加路径到 PATH 变量中。
macOS 中如何让.bash_profile 中的 shell 命令永久有效
- 可以通过
mkdir $HOME/bin
新建自己的 bin 目录,并通过PATH=$PATH:$HOME/bin
将自定义的 bin 目录加入到 PATH 变量。要写在.bashrc(linux),.bash_profile(macOS)中,用 source .bashrc 可以让文件立即生效。(亲测无卵用,.bash_profile 仅在当前 session 生效,不过 路径在.bash_profile 中写是对的) - 若是想让.bash_profile 真正生效,需要在 terminal 的偏好设置中设置,启动命令
source ~/.bash_profile
原来似曾相识的这些 bin 存放在这里
// bin 目录间用冒号分隔
echo $PATH // /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
- /usr/local/bin 存放了 brew,cnpm,docker,docsify,koa,mongo,mongod,node,npm,python3,yarn
- /usr/bin 存放了 cd,git,java 全家桶,man,python2,ssh,su,sudo,touch,unzip,vi,vim
- /bin 存放了 mv,rmdir,cat,ln,ls,kill,pwd,echo,mkdir,rm
- /usr/sbin 没有一个常用的
- /sbin ifconfig
DIY Variable
➜ ~ foo=123
➜ ~ echo $foo
123
➜ ~ bash
bash-3.2$ echo $foo
这个例子中的 bash 命令,会开启一个 daughter process,在 mother process 中设定的自定义变量是无法访问的。
设置自定义变量
new_variable="Hello"
读取自定义变量
echo $new_variable
shell 间共享自定义变量
如何在 bash daughter process 中也能访问到自定义变量呢,也就是如何在进程间共享自定义变量呢?
➜ ~ export bar=456
➜ ~ bash
bash-3.2$ echo $bar
456
从这个例子中可以看到,export 就是干这个事情的。(es6 中的 export 和这个也很类似,只有 export 的内容,其他模块才能获得数据。)
注意:在 daughter process 修改继承来的变量值,mother process 不会被修改。(这个和编程语言中的继承很像。)
查看所有的共享变量
export -p
...
export USER=frank
export OLDPWD=/
export ZSH=/Users/frank/.oh-my-zsh
export bar=456
...
OLDPWD 这个变量指的就是最近一次访问的目录,通过 cd -
访问到的其实就是这个目录。
同样,通过 env
也可以直接获得所有的环境变量列表,不同的地方在于不带 export 并且是环境变量的最终结果,export -p
会显示变量的详细配置(因为它有可能依赖其他环境变量)。
反思与总结
- 主要深入了解了 HOME,PATH 和 DIY 环境变量是什么
- 对似曾相识的 bin,.bash_profile,export 等等有了较为清晰的认知
- 主要根据参考资料 bash-variables-environmental-and-otherwise 做了一些在 macOS 环境下的一些思考和实践