在前端工程化普及的今天睦尽,前端開發(fā)的同學(xué)幾乎不可避免地要使用自動(dòng)化腳本進(jìn)行項(xiàng)目構(gòu)建,而這些腳本基本上都通過 Shell 來運(yùn)行丢间,也就是我們常說的命令行萍摊。
沒有專門學(xué)習(xí)過 Linux的同學(xué)著觉,相信大部分和我一樣,知道如何運(yùn)行已知的 Shell 命令嘉涌,使其工作妻熊,但是對其中的原理了解并不多。一旦出現(xiàn)問題仑最,排查起來會一片茫然扔役,耗費(fèi)許多時(shí)間。及時(shí)通過谷歌和度娘解決了問題词身,也不盡知其所以然厅目!
所以本著降低日后踩坑的機(jī)會想法,我決定正經(jīng)地了解一下 Shell法严。
這篇文章面向的损敷,是和我一樣正在使用 Shell 但是了解不多的同學(xué),如有錯(cuò)誤深啤,請指正拗馒。
Shell 是什么?
先扯點(diǎn)歷史溯街,對理解 Shell 有幫助诱桂。
我們平時(shí)使用的命令行界面的 Shell,只是眾多 Shell的一種呈昔。根據(jù)維基百科 Shell 中的定義挥等, Shell 是指操作系統(tǒng)中,提供訪問內(nèi)核服務(wù)的程序堤尾,與之相對的是操作系統(tǒng)的內(nèi)核( Core :在 Linux 系統(tǒng)中是 Linux Kernel )肝劲。因此,Shell 不是某一個(gè)程序,而是能提供訪問內(nèi)核服務(wù)的程序都可以歸類為 Shell 程序辞槐。那么Linux 系統(tǒng)可以簡單理解為:Linux Kernel + Shell 掷漱。
通常,根據(jù)使用方式的不同 Shell 可以分成兩類:命令行頁面( CLI )和圖形界面( GUI )榄檬。其中命令行界面(CLI)才是本文想要探索的種類卜范。
不過問題又來了,僅僅命令行界面Shell(以下簡稱CLI-Shell)鹿榜,也是有很多種類海雪,光能夠運(yùn)行在 Linux 系統(tǒng)下的,就有 Bourne shell (sh)犬缨、C shell (csh)喳魏、Korn shell (ksh)棉浸、TENEX C shell (tcsh)怀薛、Bourne-Again shell (bash)、Z shell (zsh) 等等迷郑。這些種類的由來枝恋,涉及到 CLI-Shell 的發(fā)展歷史,有興趣的同學(xué)可以閱讀:維基百科:Unix 或類似操作系統(tǒng)下的 shell嗡害,這里就不再展開焚碌。
通過運(yùn)行 cat /etc/shells
命令,可以查看機(jī)器可以使用哪些 Shell:
# List of acceptable shells for chpass(1).
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
可以看到展示的結(jié)果有6種霸妹,這還只是一部分而已十电。對于這些 Shell 的實(shí)現(xiàn), 我們也不太了解各自的不同叹螟。我們只是為了平時(shí)少踩坑鹃骂,沒必要非常深入。只需要知道以上各種 CLI-Shell 的雖然實(shí)現(xiàn)各有差異罢绽,但其基本原理都是類似的畏线,而在眾多的實(shí)現(xiàn)中,Bash 是最為廣泛使用良价,在通常的 Linux 發(fā)行版中寝殴,默認(rèn)的 Shell 就是 Bash。所以接下來的內(nèi)容明垢,都會以 Bash 為例來進(jìn)行說明蚣常。
Shell 啟動(dòng)
Shell 啟動(dòng)腳本
在平時(shí)的工作中,常常會接觸到環(huán)境變量痊银、命令別名等概念抵蚊。這些東西如何配置?又是怎么生效的?這里就涉及到啟動(dòng)腳本了泌射。Shell 的啟動(dòng)腳本粘姜,其實(shí)是為 Shell 配置工作環(huán)境的配置腳本。
Shell 不同的啟動(dòng)方式
在深入理解 Shell 啟動(dòng)腳本之前熔酷,我們需要先了解另外兩個(gè)概念:Login Shell 和 Non-login Shell孤紧。
顧名思義:
- Login Shell 就是需要經(jīng)過登錄流程才能獲得的 Shell。例如:從終端登錄或者通過 SSH 遠(yuǎn)程登錄拒秘。
-
Non-login Shell 就是不需要登錄就能獲得的 Shell号显。例如:運(yùn)行
bash
命令得到一個(gè)新的 Shell,這時(shí)并不需要登錄躺酒,所以得到的就是 Non-login Shell押蚤。
對于一個(gè)擁有圖形界面的 Linux 系統(tǒng),登錄系統(tǒng)后顯示圖形界面羹应,這時(shí)并不會打開一個(gè) Login Shell揽碘,并且在圖形界面下打開終端窗口得到的 Shell 也不是 Login Shell,這點(diǎn)非常重要园匹。
那么我們?nèi)绾闻袛嘁粋€(gè)已經(jīng)打開的 Shell 是 login 還是 non-login 的雳刺?
根據(jù) Bash 的文檔:
A login shell is one whose first character of argument zero is ‘-’, or one invoked with the --login option.
我們可以通過運(yùn)行echo $0
來查看第一個(gè)參數(shù)是否包含-
前綴來判斷:
# 在 OS X 打開的終端中
Macintosh-5:~ $ echo $0
-/bin/bash # => Login Shell
# 通過`bash`命令新打開的 Shell 中
Macintosh-5:~ $ bash
bash-3.2$ echo $0
bash # => Non-login Shell
PS:Shell 以另外一種方式還可分為 Interactive Shell 和 Non-interactive Shell。Interactive Shell 是可以等待使用者輸入進(jìn)行交互的裸违,我們一般情況下使用的在終端中輸入命令得到相應(yīng)的就是這種掖桦。Non-interactive Shell 的典型使用就是 Shell 腳本,比如:自動(dòng)化運(yùn)維腳本供汛。
Shell 啟動(dòng)腳本文件及執(zhí)行
以 Bash 為例枪汪,Shell 的啟動(dòng)腳本有以下幾個(gè):
-
/etc/profile
這個(gè)腳本中的設(shè)置對每個(gè)登錄用戶都會生效。 -
~/.bash_profile
Bash 個(gè)人設(shè)置怔昨,只會對當(dāng)前登錄的用戶生效雀久。 -
~/.bash_login
登錄 Bash 會執(zhí)行,也只會對當(dāng)前登錄的用戶生效朱监。 -
~/.profile
是通用的個(gè)人設(shè)置岸啡,僅對當(dāng)前登錄用戶生效。這個(gè)啟動(dòng)腳本是 sh 規(guī)定的( Unix 系統(tǒng)上 第一個(gè) Shell赫编,也是目前類 Unix 系統(tǒng) root 用戶的默認(rèn) Shell )巡蘸,后來發(fā)展的各種 Shell 為了兼容 sh,故一直保持一致擂送。 -
~/.bash_logout
退出登錄時(shí)執(zhí)行悦荒,也只會對當(dāng)前登錄的用戶生效。 -
~/.bashrc
Non-login Shell 的配置腳本嘹吨。
Bash Login-Shell 啟動(dòng)腳本的執(zhí)行
- 首先執(zhí)行
/etc/profile
- 然后依次查找
~/.bash_profile
搬味、~/.bash_login
和~/.profile
三個(gè)文件,找到第一個(gè)存在并且可讀的文件來執(zhí)行。Bash 規(guī)定首先查找以bash_
開頭的啟動(dòng)腳本碰纬,如果沒有萍聊,則和 sh 保持一直 查找~/.profile
并執(zhí)行。 - 如果存在
~/.bash_logout
悦析,退出時(shí)會執(zhí)行這個(gè)腳本寿桨。
值得一提的是,用戶的個(gè)人設(shè)置是可以覆蓋/etc/profile
中的全局設(shè)置的强戴。
Bash Non-login Shell 啟動(dòng)腳本的執(zhí)行
No-login Shell 啟動(dòng)時(shí)亭螟,僅會執(zhí)行~/.bashrc
以進(jìn)行配置。
OS X 上 Shell 的啟動(dòng)
OS X 也是一款類 Unix 系統(tǒng)骑歹,但是當(dāng)我們登錄后再通過打開一個(gè) Shell预烙,這時(shí)得到的是一個(gè) Login Shell,和 Linux 的并不一致道媚。關(guān)于這個(gè)情況有兩種解釋:一種說 OS X 在登錄時(shí)扁掸,不會執(zhí)行~/.profile
,它有一套自己的方式加載全局設(shè)置衰琐,所以每次以終端的方式打開一個(gè) Shell也糊,就必須執(zhí)行一遍全局設(shè)置腳本炼蹦。另一種說法比較猜測羡宙,早期的 OS X 上的默認(rèn) Shell 是 tcsh,后來蘋果的開發(fā)人員將其切換為 bash 的時(shí)候壓根 忘了這事掐隐、忘了這事……
我覺得第一種的解釋靠譜一些狗热,不過不管哪一種原因,我們來看看其中的區(qū)別虑省。
在 Linux 上匿刮,當(dāng)你登陸系統(tǒng)時(shí),系統(tǒng)就執(zhí)行/etc/profile
以及~/.bash_profile
探颈、~/.bash_login
熟丸、~/.profile
中第一個(gè)存在的。之后每次以終端的方式打開一個(gè) Shell伪节,就不再執(zhí)行這些光羞,而是繼承這些配置,并執(zhí)行~/.bashrc
怀大。
而在 OS X 上纱兑,登錄后每次以終端的方式打開一個(gè) Shell 都會執(zhí)行/etc/profile
以及~/.bash_profile
、~/.bash_login
化借、~/.profile
潜慎,這時(shí)是 Login-Shell 的啟動(dòng)方式,因此不會執(zhí)行~/.bashrc
。
Bash 啟動(dòng)腳本配置實(shí)踐( OS X )
在知悉各個(gè)啟動(dòng)腳本的特性和用途后铐炫,我們可以對機(jī)器上的啟動(dòng)配置做如下優(yōu)化:
- 將每個(gè)用戶都需要使用的通用配置加入
/etc/profile
垒手。 - 將個(gè)人的、不涉及到終端特性的通用配置加入
~/.profile
倒信。 - 將個(gè)人的淫奔、Bash 相關(guān)的配置加入
~/.bash_profile
。 - 將通用的 Bash 配置加入
./bashrc
在~/bash_profile
的頭部堤结,加入以下腳本:
[ -r ~/.profile ] && source ~/.profile
[ -r ~/.bashrc ] && source ~/.bashrc
這里使用source
命令將~/.profile
和~/.bashrc
加入~/bash_profile
中唆迁,得到了我們想要的配置。
如果在系統(tǒng)中切換使用其他的 Shell竞穷,比如 zsh唐责,也可以參照類似的方式來配置。
參考文獻(xiàn)
- Shell - 維基百科
- Invoking Bash - Bash Reference Manual
- Bash Startup Files - Bash Reference Manual
- bash啟動(dòng)腳本 - Linux C編程一站式學(xué)習(xí)
- 第十章瘾带、認(rèn)識與學(xué)習(xí)BASH - 鳥哥的 Linux 私房菜
- 交互式shell和非交互式shell鼠哥、登錄shell和非登錄shell的區(qū)別 - 笑遍世界
- Why are interactive shells on OSX login shells by default? - Unix & Linux Stack Exchange