環境變量那些事兒

一直以來,配置環境變量的時候都是管中窺豹,對於環境變量的配置似懂非懂。 如今就來認真補一補這方面的不足。java

主要內容包括:node

  • HOME
    • 爲何須要$,直接打印HOME不行嗎?
    • 一個系統下只有一個HOME變量嗎?
    • 如何override系統自定義的HOME變量?
    • 能夠在bash中直接經過$HOME訪問目錄嗎?
    • =左右有空格嗎?
    • 如何設置重寫的HOME永久有效?
  • PATH
    • macOS中如何讓.bash_profile中的shell命令永久有效
    • 原來似曾相識的這些bin存放在這裏
  • DIY Variable
    • 設置自定義變量
    • 讀取自定義變量
    • shell間共享自定義變量
    • 查看全部的共享變量

先來思考這些問題:python

  • 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文件中保存。mysql

專項學習環境變量以後的理解:洞若觀火 發現環境變量居然包括以上如此多內容,最初的問題也能夠一一找到答案。linux

接下來就來看看關於環境變量,到底有哪些須要掌握的知識點。git

HOME

這是一個指向用戶的home目錄的bash var。 格式爲/Users/<username>/var/root(macOS)。linux系統上爲/home/<username>es6

// frank用戶
echo $HOME // /Users/frank
// root用戶
echo $HOME // /var/root
複製代碼

引伸問題:github

爲何須要$,直接打印HOME不行嗎?

在bash中,只有加上$之後,系統纔會知道咱們要輸出的是變量,不然會當作輸出一個普通字符串處理。sql

一個系統下只有一個HOME變量嗎?

取決於系統上有幾個用戶,有個用戶就有幾個HOME變量。 通常會有一個root用戶和至少一個普通用戶。docker

如何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中設定的自定義變量是沒法訪問的。

爲何/usr/bin中會有java全家桶的bin呢?

難道java全家桶的命令不是存放在/Library/Java/JavaVirtualMachines/jdk-11.0.3.jdk/Contents/Home/bin嗎?爲何/usr/bin中也有。

經過ls -l /usr/bin | grep java能夠查實緣由。

lrwxr-xr-x   1 root   wheel         74  5  4 17:12 java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
lrwxr-xr-x   1 root   wheel         75  5  4 17:12 javac -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javac
lrwxr-xr-x   1 root   wheel         77  5  4 17:12 javadoc -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javadoc
lrwxr-xr-x   1 root   wheel         75  5  4 17:12 javah -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javah
lrwxr-xr-x   1 root   wheel         75  5  4 17:12 javap -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javap
lrwxr-xr-x   1 root   wheel         82  5  4 17:12 javapackager -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javapackager
lrwxr-xr-x   1 root   wheel         76  5  4 17:12 javaws -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javaws
複製代碼

soft link。 /usr/bin中的java全家桶命令只是/Library/Java/JavaVirtualMachines/jdk-11.0.3.jdk/Contents/Home/bin部分bin文件的soft link。

若是不懂soft link,能夠移步[譯]Soft and Hard links in Unxi/Linux

設置自定義變量

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環境下的一些思考和實踐
  • 沒有涉及語言層面的環境變量,例如NODE_ENV,process.env等等,可是若是掌握了上面提到的內容,對這些語言環境變量的理解也會更加輕鬆
相關文章
相關標籤/搜索