認識 BASH 這個 Shell
其實殼程式的功能只是提供使用者操作系統的一個介面,因此這個殼程式需要可以呼叫其他軟體才好。 我們在第四章到第九章提到過很多指令,包括 man, chmod, chown, vi, fdisk, mkfs 等等指令,這些指令都是獨立的應用程式, 但是我們可以透過殼程式 (就是指令列模式) 來操作這些應用程式,讓這些應用程式呼叫核心來運作所需的工作哩!
只要能夠操作應用程式的介面都能夠稱為殼程式。狹義的殼程式指的是指令列方面的軟體,包括本章要介紹的 bash 等。 廣義的殼程式則包括圖形介面的軟體!因為圖形介面其實也能夠操作各種應用程式來呼叫核心工作啊!
Linux 使用的Shell版本就稱為『 Bourne Again SHell (簡稱 bash) 』,檢查一下 /etc/shells 這個檔案可以看到本机支持的几种shell。
當我登入的時候,系統就會給我一個 shell 讓我來工作了。 而這個登入取得的 shell 就記錄在 /etc/passwd 這個檔案內!
bash的优点
- 指令記錄在你的家目錄內的 .bash_history 啦! 不過,需要留意的是,~/.bash_history 記錄的是前一次登入以前所執行過的指令, 而至於這一次登入所執行的指令都被暫存在記憶體中,當你成功的登出系統後,該指令記憶才會記錄到 .bash_history 當中!
- 命令與檔案補全功能: ([tab] 按鍵的好處)
- 命令別名設定功能:你可以在指令列輸入 alias 就可以知道目前的命令別名有哪些了!也可以直接下達命令來設定別名呦:
alias lm='ls -al'
- 工作控制、前景背景控制: (job control, foreground, background)
- 程式化腳本: (shell scripts)
- 萬用字元: (Wildcard)(『 ls -l /usr/bin/X* 』)
查詢指令是否為 Bash shell 的內建命令: type
当指令太长时,用『 \ [Enter] 』来连接
[ctrl]+u/[ctrl]+k 分別是從游標處向前刪除指令串 ([ctrl]+u) 及向後刪除指令串 ([ctrl]+k)。
[ctrl]+a/[ctrl]+e 分別是讓游標移動到整個指令串的最前面 ([ctrl]+a) 或最後面 ([ctrl]+e)。
Shell 的變數功能
這些環境變數例如 PATH、HOME、MAIL、SHELL 等等,都是很重要的, 為了區別與自訂變數的不同,環境變數通常以大寫字元來表示呢!
[dmtsai@study ~]$ echo ${myname}
<==這裡並沒有任何資料~因為這個變數尚未被設定!是空的!
[dmtsai@study ~]$ myname=VBird
[dmtsai@study ~]$ echo ${myname}
VBird <==出現了!因為這個變數已經被設定了!
unset myname //取消變數的方法為使用 unset
变数设定需要遵循一定的规则
用 env 觀察環境變數與常見環境變數說明
用 set 觀察所有變數 (含環境變數與自訂變數)
$:(關於本 shell 的 PID)
?:(關於上個執行指令的回傳值)
什麼是『子程序』呢?就是說,在我目前這個 shell 的情況下,去啟用另一個新的 shell ,新的那個 shell 就是子程序啦!在一般的狀態下,父程序的自訂變數是無法在子程序內使用的。但是透過 export 將變數變成環境變數後,就能夠在子程序底下應用了!
bash 可不只有環境變數喔,還有一些與 bash 操作介面有關的變數,以及使用者自己定義的變數存在的。
有些朋友在練習 linux 的時候喜歡同時開好幾個 bash 介面,這些 bash 的身份都是 root 。 這樣會有 ~/.bash_history 的寫入問題嗎?想一想,因為這些 bash 在同時以 root 的身份登入, 因此所有的 bash 都有自己的 1000 筆記錄在記憶體中。因為等到登出時才會更新記錄檔,所以囉, 最後登出的那個 bash 才會是最後寫入的資料。唔!如此一來其他 bash 的指令操作就不會被記錄下來了 (其實有被記錄,只是被後來的最後一個 bash 所覆蓋更新了) 。
Bash Shell 的操作環境
其實 bash 的 login shell 設定只會讀取上面三個檔案的其中一個, 而讀取的順序則是依照上面的順序。也就是說,如果 ~/.bash_profile 存在,那麼其他兩個檔案不論有無存在,都不會被讀取。 如果 ~/.bash_profile 不存在才會去讀取 ~/.bash_login,而前兩者都不存在才會讀取 ~/.profile 的意思。 會有這麼多的檔案,其實是因應其他 shell 轉換過來的使用者的習慣而已。
資料流重導向
範例三:承範例二,將 stdout 與 stderr 分存到不同的檔案去
[dmtsai@study ~]$ find /home -name .bashrc > list_right 2> list_error
範例四:承範例三,將錯誤的資料丟棄,螢幕上顯示正確的資料
[dmtsai@study ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc <==只有 stdout 會顯示到螢幕上, stderr 被丟棄了
範例五:將指令的資料全部寫入名為 list 的檔案中
[dmtsai@study ~]$ find /home -name .bashrc > list 2> list <==錯誤
[dmtsai@study ~]$ find /home -name .bashrc > list 2>&1 <==正確
[dmtsai@study ~]$ find /home -name .bashrc &> list <==正確
1> :以覆蓋的方法將『正確的資料』輸出到指定的檔案或裝置上;
1>>:以累加的方法將『正確的資料』輸出到指定的檔案或裝置上;
2> :以覆蓋的方法將『錯誤的資料』輸出到指定的檔案或裝置上;
2>>:以累加的方法將『錯誤的資料』輸出到指定的檔案或裝置上;
範例七:用 stdin 取代鍵盤的輸入以建立新檔案的簡單流程
[dmtsai@study ~]$ cat > catfile < ~/.bashrc
[dmtsai@study ~]$ ll catfile ~/.bashrc
-rw-r--r--. 1 dmtsai dmtsai 231 Mar 6 06:06 /home/dmtsai/.bashrc
-rw-rw-r--. 1 dmtsai dmtsai 231 Jul 9 18:58 catfile
# 注意看,這兩個檔案的大小會一模一樣!幾乎像是使用 cp 來複製一般!
這東西非常的有幫助!尤其是用在類似 mail 這種指令的使用上。 理解 < 之後,再來則是怪可怕一把的 << 這個連續兩個小於的符號了。 他代表的是『結束的輸入字元』的意思!舉例來講:『我要用 cat 直接將輸入的訊息輸出到 catfile 中, 且當由鍵盤輸入 eof 時,該次輸入就結束』,那我可以這樣做:
[dmtsai@study ~]$ cat > catfile << "eof"
> This is a test.
> OK now stop
> eof <==輸入這關鍵字,立刻就結束而不需要輸入 [ctrl]+d
[dmtsai@study ~]$ cat catfile
This is a test.
OK now stop <==只有這兩行,不會存在關鍵字那一行!
指令下達情況 說明
cmd1 && cmd2 1. 若 cmd1 執行完畢且正確執行($?=0
),則開始執行 cmd2。
2. 若 cmd1 執行完畢且為錯誤 ($?≠0
),則 cmd2 不執行。
cmd1 || cmd2 1. 若 cmd1 執行完畢且正確執行($?=0
),則 cmd2 不執行。
2. 若 cmd1 執行完畢且為錯誤 ($?≠0
),則開始執行 cmd2。
管線命令 (pipe)
想一想,如果你硬要讓 standard error 可以被管線命令所使用,那該如何處理?其實就是透過上一小節的資料流重導向即可! 讓 2>&1 加入指令中~就可以讓 2> 變成 1> 囉!了解了嗎? _