Linux shell 学习笔记(3)— shell 父子关系及内建命令
1. shell 類型
只要用戶登錄到某個虛擬控制臺終端或是在 GUI 中啟動終端仿真器,默認的 shell 程序就會開始運行。
默認的交互 shell 會在用戶登錄某個虛擬控制臺終端或在 GUI 中運行終端仿真器時啟動。不過還有另外一個默認 shell 是 /bin/sh,它作為默認的系統 shell,用于那些需要在啟動時使用的系統 shell腳本。
$ cat /etc/passwd
[...]
christine:x:1000:1000:Christine,,,:/home/christine:/bin/bash
$
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Apr 22 12:33 /bin/sh -> dash
可以看到,用戶 christine 默認的交互 shell 是 /bin/bash,也就是 bash shell。但是作為默認系統shell 的 /bin/sh 被設置為 dash shell。
2. shell 的父子關系
用于登錄某個虛擬控制器終端或在 GUI 中運行終端仿真器時所啟動的默認的交互 shell,是一個父shell。父 shell 提供 CLI 提示符,然后等待命令輸入。
在 CLI 提示符后輸入 /bin/bash 命令或其他等效的 bash 命令時,會創建一個新的 shell 程序。這個shell 程序被稱為子 shell(child shell)。子 shell 也擁有 CLI 提示符,同樣會等待命令輸入。
$ ps -f
UID PID PPID C STIME TTY TIME CMD
501 1841 1840 0 11:50 pts/0 00:00:00 -bash
501 2429 1841 4 13:44 pts/0 00:00:00 ps -f
$
$ bash
$
$ ps -f
UID PID PPID C STIME TTY TIME CMD
501 1841 1840 0 11:50 pts/0 00:00:00 -bash
501 2430 1841 0 13:44 pts/0 00:00:00 bash
501 2444 2430 1 13:44 pts/0 00:00:00 ps -f
注意:進程就是正在運行的程序。bash shell 是一個程序,當它運行的時候,就成為了一個進程。一個運行著的 shell 就是某種進程而已。
子 shell 的父進程 ID(PPID)是 1841,指明了這個父 shell 進程就是該子 shell 的父進程。
子 shell(child shell,也叫 subshell)可以從父 shell 中創建,也可以從另一個子 shell 中創建。
$ ps -f
UID PID PPID C STIME TTY TIME CMD
501 1841 1840 0 11:50 pts/0 00:00:00 -bash
501 2532 1841 1 14:22 pts/0 00:00:00 ps -f
$
$ bash
$
$ bash
$
$ bash
$
$ ps --forest
PID TTY TIME CMD
1841 pts/0 00:00:00 bash
2533 pts/0 00:00:00 \_ bash
2546 pts/0 00:00:00 \_ bash
2562 pts/0 00:00:00 \_ bash
2576 pts/0 00:00:00 \_ ps
bash 命令被輸入了三次。這實際上創建了三個子 shell。ps -forest 命令展示了這些子 shell 間的嵌套結構。
可以利用 exit 命令有條不紊地退出子 shell。exit 命令不僅能退出子 shell,還能用來登出當前的虛擬控制臺終端或終端仿真器軟件。只需要在父 shell 中輸入 exit,就能夠從容退出 CLI 了。
2.1 進程列表
在一行中輸入多個命令,只需要在命令之間加入分號 ; 即可:
$ pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls
/home/Christine
Desktop Downloads Music Public Videos
Documents junk.dat Pictures Templates
/etc
/home/Christine
Desktop Downloads Music Public Videos
Documents junk.dat Pictures Templates
命令列表要想成為進程列表,這些命令必須包含在括號里。
$ (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)
/home/Christine
Desktop Downloads Music Public Videos
Documents junk.dat Pictures Templates
/etc
/home/Christine
Desktop Downloads Music Public Videos
Documents junk.dat Pictures Templates
$
在 shell 腳本中,經常使用子 shell 進行多進程處理。但是采用子 shell 的成本不菲,會明顯拖慢處理速度。在交互式的 CLI shell 會話中,子 shell 同樣存在問題。它并非真正的多進程處理,因為終端控制著子 shell 的 I/O。
2.2 子 shell 的其它用法
后臺模式: 在后臺模式中運行命令可以在處理命令的同時讓出 CLI,以供他用,要想將命令置入后臺模式,可以在命令末尾加上字符 &
$ sleep 3000&
[1] 2396
$ ps -f
UID PID PPID C STIME TTY TIME CMD
christi+ 2338 2337 0 10:13 pts/9 00:00:00 -bash
christi+ 2396 2338 0 10:17 pts/9 00:00:00 sleep 3000
christi+ 2397 2338 0 10:17 pts/9 00:00:00 ps -f
$
jobs 命令可以顯示出當前運行在后臺模式中的所有用戶的進程(作業)。
$ jobs
[1]+ Running sleep 3000 &
$
jobs 命令在方括號中顯示出作業號(1)。它還顯示了作業的當前狀態(running)以及對應的命令(sleep 3000 &)
利用 jobs 命令的 -l(字母L的小寫形式)選項還能夠顯示出命令的 PID
$ jobs -l
[1]+ 2396 Running sleep 3000 &
$
[1]+ Done sleep 3000 &
$
生成子shell的成本不低,而且速度還慢。創建嵌套子shell更是火上澆油!
3. 理解 shell 的內建命令
3.1 外部命令
外部命令: 有時候也被稱為文件系統命令,是存在于 bash shell 之外的程序。它們并不是 shell程序的一部分。
外部命令程序通常位于 /bin、/usr/bin、/sbin或 /usr/sbin中。
ps 就是一個外部命令。你可以使用 which 和 type 命令找到它。
$ which ps
/bin/ps
$
$ type -a ps
ps is /bin/ps
$
$ ls -l /bin/ps
-rwxr-xr-x 1 root root 93232 Jan 6 18:32 /bin/ps
$
當外部命令執行時,會創建出一個子進程。這種操作被稱為衍生(forking)。外部命令 ps 很方便顯示出它的父進程以及自己所對應的衍生子進程。
$ ps -f
UID PID PPID C STIME TTY TIME CMD
christi+ 2743 2742 0 17:09 pts/9 00:00:00 -bash
christi+ 2801 2743 0 17:16 pts/9 00:00:00 ps -f
$
3.2 內建命令
內建命令和外部命令的區別在于前者不需要使用子進程來執行。它們已經和 shell 編譯成了一體,作為 shell 工具的組成部分存在。不需要借助外部程序文件來運行。
cd 和 exit 命令都內建于 bash shell。可以利用 type 命令來了解某個命令是否是內建的。
$ type cd
cd is a shell builtin
$
$ type exit
exit is a shell builtin
$
因為既不需要通過衍生出子進程來執行,也不需要打開程序文件,內建命令的執行速度要更快,效率也更高。
要查看命令的不同實現,使用 type 命令的 -a 選項
$ type -a echo
echo is a shell builtin
echo is /bin/echo
$
$ which echo
/bin/echo
$
$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd
$
$ which pwd
/bin/pwd
$
命令type -a顯示出了每個命令的兩種實現。注意,which命令只顯示出了外部命令文件。
總結
以上是生活随笔為你收集整理的Linux shell 学习笔记(3)— shell 父子关系及内建命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux shell 学习笔记(2)—
- 下一篇: Linux shell 学习笔记(4)—