了解子 shell 和 父 shell 之間的關(guān)系以及一些命令
更多精彩
- 更多技術(shù)博客,請移步 IT人才終生實(shí)訓(xùn)與職業(yè)進(jìn)階平臺(tái) - 實(shí)訓(xùn)在線
5.1 shell 的類型
- Linux 中,用戶使用的 shell 類型,被配置在 /etc/passwd 文件中,通常都是 bash shell
- 除了 bash shell ,CentOS 中一般還內(nèi)置了 tcsh shell 、dash shell 、ash shell、tcsh shell
- 查看當(dāng)前系統(tǒng)是否內(nèi)置了上述 shell 類型,可以通過如下方式
- 可以看到,在下圖的 CentOS 環(huán)境中,只存在 bash shell 和 dash shell
- 可以看到,在下圖的 CentOS 環(huán)境中,只存在 bash shell 和 dash shell
- 但在 macOS 環(huán)境中,除了 ash shell 沒有內(nèi)置,其他的幾種類型都可以找到
5.1.1 默認(rèn)的系統(tǒng) shell
- 在用戶配置文件與用戶綁定的 shell 會(huì)在系統(tǒng)啟動(dòng)時(shí)運(yùn)行
- 但除了啟動(dòng)用戶 shell 之外,還會(huì)啟動(dòng)一個(gè)系統(tǒng) shell ,通常被指定為 /bin/sh ,如下圖
- 但是可以看到,/bin/sh 只是 bash shell 的軟鏈接
- 不過不是所有的系統(tǒng)的默認(rèn)系統(tǒng) shell 都指向 bash shell ,Ubuntu 通常會(huì)指向 dash shell
5.2 shell 的父子關(guān)系
- 父 shell 是指用于登錄系統(tǒng)的默認(rèn) shell
- 子 shell 則是在 父 shell 環(huán)境中創(chuàng)建的其他 shell
- 使用
bash命令可以在 父 shell 中創(chuàng)建 子 shell ,如下圖-
ps -f命令第一次執(zhí)行時(shí),只能獲取兩條進(jìn)程信息,-bash 則是當(dāng)前的 父 shell - 在執(zhí)行
bash命令后,再次執(zhí)行ps -f命令則獲取到了三條進(jìn)程信息,bash 則是剛才通過執(zhí)行bash命令創(chuàng)建的 子 shell -
bash 進(jìn)程的 PPID 和 -bash 進(jìn)程的 PID 一致,說明后者是前者的父級
-
-
bash命令提供了一些指令,如下圖
- 使用
exit退出當(dāng)前 shell ,如下圖- 使用
bash創(chuàng)建一個(gè) 子 shell 后 - 執(zhí)行
exit,再次執(zhí)行ps -f,之前創(chuàng)建的 子 shell 進(jìn)程就不存在了
- 使用
- 子 shell 并不是真正的多進(jìn)程處理,層級過多的 子 shell 會(huì)帶來更多的系統(tǒng)花銷,拖慢處理速度
5.2.1 進(jìn)程列表
- 在介紹 進(jìn)程列表 之前,需要先了解 命令列表
-
命令列表 是在多個(gè)命令之間通過分號分隔,讓一行中的命令可以依次執(zhí)行,如下圖
-
可以看到,命令被依次執(zhí)行并輸出了結(jié)果
-
-
命令列表 想要進(jìn)化成 進(jìn)程列表 ,只需要在這些命令兩側(cè)加上括號即可,如下圖
5.2.1.1 命令列表和進(jìn)程列表的區(qū)別
- 那么你可能會(huì)問,只是加了括號,但輸出結(jié)果一致,這兩個(gè)列表的區(qū)別在哪
- 區(qū)別在于:命令列表 是直接執(zhí)行這些命令串
- 但 進(jìn)程列表 會(huì)創(chuàng)建一個(gè) 子 shell 開執(zhí)行這些命令,執(zhí)行完畢后 子 shell 也會(huì)隨之結(jié)束
- 使用
echo $BASH_SUBSHELL命令可以更清晰的知道命令在執(zhí)行時(shí),是否存在 子 shell ,如下圖- 如果不存在,會(huì)返回 0 ,否則就是存在
- 返回?cái)?shù)字的表達(dá)意思是 進(jìn)程列表 的嵌套層級
5.2.2 別出心裁的子 shell 用法
5.2.2.1 & 命令探索后臺(tái)模式
- 在后臺(tái)模式中執(zhí)行命令可以在處理命令的同時(shí)讓出 CLI ,以供他用
- 在待執(zhí)行命令的末尾添加字符
&,可以讓該命令在后臺(tái)執(zhí)行,如下圖-
sleep 5命令表示當(dāng)前線程會(huì)等待 5 秒,如果直接執(zhí)行,當(dāng)前命令行會(huì)在 5 秒后才能繼續(xù)接收輸入 -
sleep 5 &命令執(zhí)行后則會(huì)立即返回一個(gè)后臺(tái)任務(wù) ID ,以及該進(jìn)程的 PID ,當(dāng)前命令行也可以立即接收新的輸入 - 需要注意的是 macOS 在命令執(zhí)行完畢后,會(huì)自動(dòng)輸出執(zhí)行結(jié)果,如下圖
- 但 CentOS 不會(huì)自動(dòng)輸出執(zhí)行結(jié)果,需要再次執(zhí)行
jobs命令,才可以看到執(zhí)行結(jié)果
-
5.2.2.2 jobs 命令查看后臺(tái)進(jìn)程
- 使用
jobs命令可以顯示當(dāng)前運(yùn)行在后臺(tái)模式中的所有用戶的進(jìn)程信息 - 使用
jobs -l則可以更詳細(xì)的顯示進(jìn)程信息,如下圖-
jobs命令會(huì)顯示后臺(tái)進(jìn)程的任務(wù) ID 、PID 、進(jìn)程狀態(tài)、進(jìn)程命令 - 同時(shí)當(dāng)后臺(tái)進(jìn)程執(zhí)行完畢后,也就無法通過
jobs查看對應(yīng)進(jìn)程信息
-
5.2.2.3 將進(jìn)程列表置入后臺(tái)
- 將 進(jìn)程列表 置入后臺(tái)運(yùn)行的好處在于:既可以在子 shell 中執(zhí)行復(fù)雜的處理工作,又不會(huì)占用當(dāng)前的 shell 窗口 ,如下圖
5.2.2.4 coproc 命令實(shí)現(xiàn)協(xié)程
- 協(xié)程 是指在后臺(tái)生成一個(gè) 子 shell ,并在這個(gè) 子 shell 中執(zhí)行命令
- 使用
coproc命令可以實(shí)現(xiàn)協(xié)程,如下圖- 可以看到,使用
jobs命令查看到的進(jìn)程命令名稱最后有一個(gè)&符號,說明這也是一個(gè)后臺(tái)進(jìn)程
- 可以看到,使用
- 上圖中大寫的 COPROC 是在使用
coproc命令時(shí)指定的默認(rèn)協(xié)程名稱 - 這個(gè)名稱是可以自定義的,如下圖
- 完整的語法是
coproc coprocName { command; } -
命令中的花括號、空格、分號缺一不可,語法格式非常嚴(yán)格
- 完整的語法是
5.3 理解 shell 的內(nèi)建命令
5.3.1 外部命令
- Linux 中存在 內(nèi)建命令 和 外部命令 ,可以先理解一下 外部命令
- 外部命令 也被稱為 文件系統(tǒng)命令 ,不是 shell 程序的一部分
- 外部命令 通常被放置在 /bin 、/usr/bin 、/sbin 、/usr/sbin 中
- 外部命令 在執(zhí)行時(shí),會(huì)創(chuàng)建一個(gè)子進(jìn)程,在子進(jìn)程中執(zhí)行該命令,這個(gè)行為被稱為 衍生( Forking )
5.3.1.1 which 命令和 type 命令查看命令歸屬
- 使用
which命令和type命令可以查看指定命令是屬于 外部命令 ,還是 內(nèi)建命令 ,如下圖-
ps命令位于 /bin 中,說明ps命令就是 外部命令
-
5.3.2 內(nèi)建命令
- 內(nèi)建命令 和 外部命令 的區(qū)別在于,內(nèi)建命令 不需要使用子進(jìn)程來執(zhí)行命令
- 內(nèi)建命令 和 shell 是一體的,作為 shell 工具的組成部分而存在
- 內(nèi)建命令 因?yàn)椴恍枰ㄟ^衍生行為來執(zhí)行,所以執(zhí)行速度會(huì)更快、效率更高
- 使用
which命令和type命令也可以查看該命令是否屬于 內(nèi)建命令 ,如下圖- 可以看到,
cdexitpwd命令都屬于 內(nèi)建命令
- 可以看到,
5.3.2.1 type -a 命令查看命令的多種實(shí)現(xiàn)
- 有些命令存在多種實(shí)現(xiàn),使用
type -a可以將該命令的全部實(shí)現(xiàn)列舉出來,如下圖- 可以看到,
pwdecho命令既是 內(nèi)建命令 ,也在 /bin 目錄中有一份實(shí)現(xiàn)
- 可以看到,
5.3.2.2 history 命令查看使用過的歷史命令
- 首先
history命令是一個(gè) 內(nèi)建命令 - 可以通過
history命令查看之前使用過的命令,如下圖- 在 CentOS 中,
history命令默認(rèn)最多可以存儲(chǔ) 1000 條歷史命令,但這個(gè)值可以通過 HISTSIZE 的環(huán)境變量進(jìn)行修改 - 下圖中只列出了 6 條數(shù)據(jù),是因?yàn)闉榱朔奖泔@示,使用
history -c命令刪除了之前的所有歷史數(shù)據(jù)
- 在 CentOS 中,
5.3.2.3 !! 命令直接執(zhí)行最近一條歷史命令
- 使用
!!命令可以直接在新的一行顯示出上一條剛剛執(zhí)行過的命令,如下圖-
!!命令執(zhí)行之后,在下一行出現(xiàn)的pwd命令不是手動(dòng)輸入的,而是由!!命令呼出的 -
呼出的命名不會(huì)直接執(zhí)行,只是顯示出來,需要手動(dòng)按回車鍵,才能再次執(zhí)行該命令
-
5.3.2.4 在 .bash_history 文件中查看命令歷史記錄
- 使用
history命令查看的命令歷史記錄,被存放在根目錄的 .bash_history 文件中 - 需要注意的是,命令的歷史記錄并不是直接存放到該文件,而是先存放到內(nèi)存中,當(dāng) shell 退出時(shí),才被寫入到該文件
- 想要強(qiáng)制將命令歷史記錄寫入文件中,可以使用
history -a命令
5.3.2.5 alias 命令實(shí)現(xiàn)為命令指定別名
-
alias命令也是一個(gè) 內(nèi)建命令 - 需要注意的是,直接使用命令創(chuàng)建的別名,只能在當(dāng)前會(huì)話生效,無法做到全局生效
- 想要全局生效,則需要將別名寫入配置文件中,后續(xù)章節(jié)會(huì)有介紹
- 使用
alias命令可以為某個(gè)復(fù)雜的命令指定一個(gè)簡單的別名,從而將調(diào)用命令的輸入減少到最低,如下圖- 可以看到,通過
alias命令將ls -al命令指向ll命令 - 之后再輸出
ll命令,就可以得到和ls -al命令一樣的結(jié)果
- 可以看到,通過
5.3.2.6 alias -p 命令查看當(dāng)前有多少命令別名
- 使用
alias -p命令可以列出當(dāng)前系統(tǒng)中存在哪些命令別名可以使用,如下圖
- 上圖是 CentOS 的效果,如果是 macOS ,無法使用
alias -p命令,直接使用alias命令,不加任何后綴即可
5.4 小結(jié)
- shell 之間存在父子級關(guān)系
- 使用
bash命令可以創(chuàng)建 子 shell - 使用
exit命令可以退出 子 shell - 使用
&命令可以將命令置入后臺(tái) - 使用
coproc命令可以在子進(jìn)程中執(zhí)行命令 - 命令列表 是指在多個(gè)命令之間添加分號,可以依次執(zhí)行命令
- 進(jìn)程列表 是指在 命令列表 外部添加一對括號,可以將這些命令在子進(jìn)程中執(zhí)行
- 使用
history命令可以查看命令歷史記錄 - 使用
!!命令可以快速呼出最近依次的命令歷史記錄 - 使用
alias命令可以給長命令指定短別名




















