Shell 簡介
當我們登入主機之後,第一個接觸到的,便是 shell。在開始學習 shell 之前,
我們必須先對它有點認識才行。
1.1 Shell 是什麼?
Linux/BSD 系統可分成三個重要的部份:
1. 核心(kernel)
2. shell
3. 工具程式
核心的部份相當低階,操作者不易和它直接溝通,因此,必須要有一個友善的介
面(interface),讓使用者在操作時能更為方便,這個介面便是 shell。換言之,
shell 就是一個居於系統核心和操作者之間方便溝通的介面。
那麼,為何稱它為 shell 呢? shell 的本意,其實是「殼」的意思。
沒錯,在核心的外面,包覆著一層外殼,用來負責接收使用者輸入的指令,然後將
指令解譯成核心能夠了解的方式,傳送給核心去執行,核心執行後,再將結果傳回
至預設的輸出周邊 (例如螢幕) 。因此,習慣上便稱它為 shell,意即核心的外殼。
Chapter
01
3Chapter 01 Shell 簡介 1.1 Shell 是什麼?
所謂「讀取使用者輸入種類的不同」是指:shell 讀取自鍵盤、滑鼠、觸控螢幕、
或其他串列輸入設備,再予以解譯指令。這樣說來,shell 好像只是一種命令直譯
器罷了?!嗯,這倒要按不同的 OS(作業系統)所賦予 shell 的功能與選擇性的
自由度而定。
以 DOS 的 COMMAND.COM 而言,它就是一個不折不扣的命令直譯器,除了一
點點 batch 檔的能力之外,其他的功能並不多。 Windows 平台的 GUI,則是一種
圖型式的命令直譯器,介面十分友善。不過,這兩種 OS,不能讓你自由而簡單地
選擇 shell(雖然以前 DOS 時代,有個 4dos 可選用,但其他選擇性不多)。
Linux/BSD 的 shell,除了做為命令直譯器之外,它也是一個不錯的程式語言,是
系統維護管理時的重要工具。
由於 Unix-like 家族的作業系統(例如 Linux/BSD),對 shell 的處理,採取獨
立、自由開放的政策,因此,shell 的種類相當地多,更可以讓人自由地更換(使
用 chsh 指令)。
目前流行的 shell 有:
序號 shell 名稱 執行檔名 原始開發者有無開放原始碼的版本/或衍生版本
授權協議
1 Bourne shell(sh) /bin/shStephen Bourne
有(4.4BSD-Lite以後),Charles Forsyth 版本
BSD/Public Domain
2Bourne Again shell(bash)
/bin/bash Brian Fox 有 GPL
3Korn shell 93(ksh93)
/bin/ksh David Korn 有 CPL
4Public Domain Korn shell(pdksh)
/bin/ksh Eric Gisin 有
Public Domain (公眾所有)
5 C shell(csh) /bin/csh Bill Joy 有 BSD
6Tenex C shell(tcsh)
/bin/tcsh Ken Greer 有 BSD
佈署 Bash shell 的環境
在學習 shell 程式設計之前,要先有一個不錯的環境,方能快意入門。
以下介紹準備環境。
2.1 在 Linux 平台佈署 Bash shell 的環境
首先,您要安裝一套 GNU/Linux 作業系統,例如 Debian、Mint、Ubuntu、
Slackware、CentOS、Fedora、Mandriva、ArchLinux 等等。這些 Linux 套件
(往後簡稱 Linux),安裝方法都十分簡單,這裡就不再贅述。
由於大部份 Linux,登入主機時,預設使用的 login shell 是使用 Bash shell,因
此,您要做的事,就是確認一下 Bash 是否存在即可。<註2-1>
確認的方法,請進入終端機程式中(例如:Gnome-terminal),執行以下指令:
echo $SHELL
若出現 /bin/bash,則表示預設的 shell,的確是 Bash。接著執行:
ls -la /bin/sh
Chapter
02
21Chapter 02 佈署 Bash shell 的環境 2.4 在 FreeBSD 平台佈署 Bash shell 的環境
2.4 在 FreeBSD 平台佈署 Bash shell 的環境
FreeBSD 預設使用的 shell 是 tcsh。
有兩種方法可以安裝 bash 套件。
第一種,是安裝 FreeBSD 的 package,即已編譯好的二進位檔;第二種是由
ports tree 進行編譯安裝。
使用 package 安裝 bash
先設定環境變數 PACKAGEROOT,指向要抓取 package 檔的站台:
setenv PACKAGEROOT ftp://ftp.tw.freebsd.org
執行:
pkg_add -r bash
其中,選項 -r 是指由遠端主機抓取套件來安裝的意思。
這樣,就可以立即把 bash 安裝妥當,其執行檔的路徑位置為 /usr/local/bin/
bash。
使用 ports tree 安裝 bash
ports tree 是 FreeBSD 團隊整理好的編譯設定檔,使用時,它會由列表的 FTP 站
台去抓取套件的原始碼回來編譯安裝。
這裡假定您已有安裝 ports tree 了。
首先,設定要抓取套件的 FTP 站台列表。若能指向國內的站台,當然,下載檔案
的速度,就會比國外快很多。
22 Chapter 02 佈署 Bash shell 的環境 2.5 在 OpenBSD 平台佈署 Bash shell 的環境
修改 /etc/make.conf,加入:
MASTER_SITE_BACKUP?= \ftp://ftp.tw.freebsd.org/pub/FreeBSD/distfiles/${DIST_SUBDIR}/\ftp://ftp2.tw.freebsd.org/pub/FreeBSD/distfiles/${DIST_SUBDIR}/\ftp://ftp3.tw.freebsd.org/pub/FreeBSD/distfiles/${DIST_SUBDIR}/MASTER_SITE_OVERRIDE?= ${MASTER_SITE_BACKUP}
接著,編譯安裝 bash:
cd /usr/ports/shell/bashmake install clean
經過一點時間之後,若編譯成功,執行檔一樣會安裝在 /usr/local/bin/bash。
切換使用 Bash shell
切換 Bash shell 的方法和 2-3 節所述類似,不過,不必事先編輯 /etc/shells,在
進行本節前面兩個動作時,安裝程式會把 /usr/local/bin/bash 自動加入 /etc/shells
之中,因此,您唯一要做的事便是執行 chsh 來切換 bash shell 即可。
以 ols3 帳號為例,執行 chsh,它會自動叫用 vi 或 ee 來做編輯(以下內容視各人
帳號不同而異),如下所示:
#Changing user information for ols3.Shell: /bin/cshFull Name: User &Office Location:Office Phone:Home Phone:Other information:
請把 /bin/csh 改成 /usr/local/bin/bash,然後,存檔離開,它會要求輸入 ols3 的
密碼:
/etc/pw.OElnwl: 7 lines, 148 characters.Password:
若密碼正確,會出現切換成功的訊息:
23Chapter 02 佈署 Bash shell 的環境 2.5 在 OpenBSD 平台佈署 Bash shell 的環境
chsh: user information updated
除了上述方法之外,直接執行以下指令也是可以的:
chsh -s /usr/local/bin/bash 帳號例如:chsh -s /usr/local/bin/bash ols3
若帳號名稱和已登入者相同,帳號可以省略不寫:
chsh -s /usr/local/bin/bash
切換 shell 之後,請重新登入主機,這樣新的 shell 環境才會生效。請執行 echo
$SHELL 和 echo $BASH_VERSION,查看一下路徑和版本是否正確。
echo $SHELL 會出現 /usr/local/bin/bashecho $BASH_VERSION 出現 4.2.20(0)-release
如果是這樣的話,就是切換成功了。
2.5 在 OpenBSD 平台佈署 Bash shell 的環境
OpenBSD 預設使用 pdksh。以帳號 ols3 為例,echo $SHELL 會出現 ksh:
$ echo $SHELL/bin/ksh
和 FreeBSD 一樣,OpenBSD 也可以用 package 或 ports tree 安裝 bash。
使用 package 安裝 bash
設定環境變數 PKG_PATH,指向要抓取 package 檔的站台,這裡是以 OpenBSD
5.2 i386 的版本為例:
export PKG_PATH=\ftp://ftp.openbsd.org/pub/OpenBSD/5.2/packages/i386/
24 Chapter 02 佈署 Bash shell 的環境 2.6 在 Windows 平台佈署 Bash shell 的環境
安裝 bash 的 package:
# pkg_add bash
結果如下:
bash-4.2.36: libiconv-1.14: okbash-4.2.36: gettext-0.18.1p3: okbash-4.2.36: ok
這樣,bash 4.2.36 版就安裝好了。安裝時,bash 套件也會自動把 /usr/local/bin/
bash 的路徑加入 /etc/shells 中,這樣一來,bash 就列表為系統合法的 shell 了。
使用 ports tree 安裝 bash
切換到 bash port 目錄,然後編譯安裝:
cd /usr/ports/shell/bashmake install clean
執行檔路徑可用 which 查詢:
# which bash/usr/local/bin/bash
/etc/shells 會自動加入 bash:
/bin/sh/bin/csh/bin/ksh/usr/local/bin/bash
切換使用 bash
一樣執行 chsh:
# Changing user database information for ols3.Shell: /bin/ksh
25Chapter 02 佈署 Bash shell 的環境 2.6 在 Windows 平台佈署 Bash shell 的環境
Full Name: ols3Office Location:Office Phone:Home Phone:
請把 /bin/ksh 改成 /usr/local/bin/bash。
或者執行以下指令直接切換:
chsh -s /usr/local/bin/bash
重新登入主機後,bash 當做 login shell 的設定,即可生效。
2.6 在 Windows 平台佈署 Bash shell 的環境
筆者推薦兩種可在 Windows 平台執行的 Linux-like 環境。
1. Cygwin
2. MSYS
Cygwin 原是由 Cygnus Solutions 開發的,主要功能是把自由軟體基金會的 GNU
工具及函式庫移植到 Windows 平台,後來,雖然 Cygnu 被 RedHat 公司收購
了,但仍以自由軟體的授權協議發行,因此,包括二進位檔及原始程式碼,都可
以繼續自由、免費地使用。
Cygwin 創建了一個 Windows 平台的 Linux-like 環境,您可在這個環境中,
把 Linux 平台的程式移植到 Windows 平台來(不過,程式的原始碼,必須在
Cygwin 的環境中,重新編譯才行)。Cygwin 以 DLL 檔的方式,模擬 Linux 的
API 函式,並提供在 Linux 平台中常用的工具包。由於Cygwin 是以一對一的方式
將 Linux 的 API 函式轉換成 Windows 平台的函式,因此,在 Cygwin 中開發的程
式,大部份應該也可以在不加修改的情況下,移植回 Linux 平台才對。
MSYS 則是著名的 MinGW 計劃(在 Windows 平台提供 GCC 編譯器的工具包)
的一個子計劃。MSYS 是 Minimal SYStem 的簡稱,它在 Windows 平台提供
GNU 的基本工具以及 shell 命令環境。
基礎概念介紹
在進入接下來的章節之前,要先介紹一點點基本觀念,以作為了解 shell 程式
設計的基礎。
3.1 登入、登出
登入主機
登入主機,可分為:「本機登入」(local login),以及「遠端登入」(remote
login)。
所謂「本機登入」是說:操作者直接面對主機,由主機的鍵盤輸入帳號密碼;所
謂「遠端登入」是說:操作者並不直接面對主機,而是透過網路連接主機,由其
他地方以虛擬終端機的方式登入。
本機登入的介面,可以是文字介面,或是圖型介面。通常 Linux/BSD 系統,預設
會開啟 7 個終端機,即 tty1 ~ tty7。文字介面的主機登入,佔用 tty1 ~ tty6;圖型
介面的主機登入,則佔用 tty7。欲在各終端機之間切換,可鍵入 Ctrl+Alt+F1(即
tty1)~ Ctrl+Alt+F7(即 tty7) 等組合鍵。
Chapter
03
34 Chapter 03 基礎概念介紹 3.2 檔案、目錄
█ 隱藏檔:
檔名的第一個字元是「.」。隱藏檔可以是前面所提到的任何一種檔案型態。
不同的檔案型態,各有其代碼,如下表所示:
型態代碼 檔案型態
- 一般檔案
d 目錄
l 符號連結檔
b 區塊設備檔
c 字元設備檔
s Socket 檔
p 管線檔
我們可以使用 ls 指令,來查看檔案的型態代碼,從而得知該檔案的型態。
例如:
ls -la /etc/resolv.conf-rw-r--r-- 1 root root 66 2009-02-21 00:58 /etc/resolv.conf
最左邊的字元,代表檔案型態。resolv.conf 的型態代碼是「-」,因此,它是一般
檔案。
又例如:
ls -ld /usrdrwxr-xr-x 16 root root 4096 2009-01-01 10:38 /usr
最左邊的字元是「d」,因此,/usr 是目錄。
除了使用 ls 指令之外,還可以用 file 這支工具。
file 的用法如下:
file 檔案路徑
35Chapter 03 基礎概念介紹 3.2 檔案、目錄
舉幾個列子:
1. file /etc/resolv.conf
執行結果:
/etc/resolv.conf: ASCII text
這表示 resolv.conf 是一個純文字檔,屬一般檔案。
2. file /usr/bin
執行結果:
/usr/bin: directory
這表示,/usr/bin 是一個目錄。
3. file /usr/bin/ssh
執行結果:
/usr/bin/ssh: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped
這表示,/usr/bin/ssh 是一個二進位檔,具有執行權。
4. file /root/tmp/test.sh
執行結果:
/root/tmp/test.sh: Bourne-Again shell script text executable
這表示,test.sh 是一個 bash script 文字檔,具執行權。
5. file /dev/tty1
執行結果:
/dev/tty1: character special (4/1)
這表示,/dev/tty1 是一個字元設備檔。
48 Chapter 03 基礎概念介紹 3.5 括號擴展
注意!若「!」不是放在集合的第一個位置,就失去「非 的作用。例如:
[0-9!]:代表數字或驚嘆號。
若一定要把「!」擺在第一個位置,又不讓它有「非」的作用,也是可以的,但此
時就要用「\!」消除其「非」的意義。例如:
[\!0-9]:代表驚嘆號或數字。
讀者若有學過其他程式語言的正規表示式(例如 Perl),須注意「.」及「*」這個
兩字元的用法,和其他語言是有所不同的。例如:[123.*] 指的是 1、2、3、「.」
或「*」這 5 個字元的其中一個,此外,並沒有其他特殊的涵義。
3.5 括號擴展
括號擴展(Brace Expansion)
字元集合,代表某一範圍中的單一字元,在組成樣式時,仍有不足。例如:想要
找出目錄 /usr/bin 中的檔案 gftp、ncftp、sftp,光用字元集合,不容易設計檔名樣
式,我們需要可組合任意字串樣式的能力才行,括號擴展的功能,則可以符合這
項需求。
括號擴展的符號是 {},它的用途是「組合」字串,例如 {g,nc,s}ftp 的意思是:拿
{} 中列舉的字串,分別和 ftp 組合起來,因此,它代表 gftp、ncftp 和 sftp。
以前述的例子來說,ls -la /usr/bin/{g,nc,s}ftp 便可一次找出這三個檔案。
再舉幾個例子:
1. 執行 ls -la /usr/{sb,b}in/*er
可找出在 /usr/sbin 和 /usr/bin 目錄中,以 er 結尾的檔案,例如:/usr/sbin/
adduser、/usr/bin/finger。
2. echo s{ab,cd}y:顯示 saby 和 scdy 這兩個字串。