Contents ...
udn網路城邦
shell的基礎
2015/10/14 20:17
瀏覽61
迴響0
推薦0
引用0
1:什麽是shell

shell的本意是“殼”的意思,其實已經很形象地說明了shell在Linux系統中的作用。shell就是圍繞在Linux內核之外的一個“殼”程序,用戶在操作系統上完成的所有任務都是通過shell與Linux系統內核的交互來實現的。我們應該熟悉DOS系統中command.com程序,shell的功能與此類似,但是shell的功能更加強大,更加好用。

各種操作系統都有自己的shell。以DOS為例,它的shell就是command.com程序。DOS下還出現了很多第三方命令解釋程序,例如4DOS、NDOS等,這些命令解釋程序完全可以取代標準的command.com程序。同樣,Linux下除了默認的Bourne again shell(bash),還有很多其他的shell,例如C shell(csh)、Korn shell(ksh)、Bourne shell(sh)和Tenex C shell(tcsh)等。每個版本的shell功能基本相同,但各有千秋,現在的Linux系統發行版一般都以bash作為默認的shell。

shell本身是一個C語言編寫的程序,是用戶和操作系統內核之間通信的橋梁。shell既是一種命令解釋程序,又是一種功能強大的解釋型程序設計語言。作為命令解釋程序,shell解釋用戶輸入的命令,然後提交到內核處理,最後把結果返回給用戶。

為了加快命令的運行,同時更有效地定制shell程序,shell中定義了一些內置的命令,一般我們把shell自身解釋執行的命令稱為內置命令,例如下面我們將要講到的cd、pwd、exit和echo等命令,都是屬於bash的內置命令。當用戶登錄系統後,shell以及內置命令就被系統載入到內存,並且一直運行,直到用戶退出系統為止。除了內置命令,Linux系統上還有很多可執行文件。可執行文件類似於Windows下的.exe文件,這些可執行文件也可以作為shell命令來執行。其實Linux上很多命令都不是shell的內置命令,例如ls就是一個可執行文件,存放在/bin/ls中。這些命令與shell內置命令不同,只有當它們被調用時,才由系統裝入內存執行。

當用戶登錄系統後,如果是登錄字符界面,將出現shell命令提示符。“#”表示登錄的用戶是系統超級用戶,“*”表示登錄到系統的是普通用戶。shell執行命令解釋的具體過程為:用戶在命令行輸入命令提交後,shell程序首先檢測是否為內置命令,如果是,就通過shell內部的解釋器將命令解釋為系統調用,然後提交給內核執行;如果不是shell內置的命令,那麽shell會按照用戶給出的路徑或者根據系統環境變量的配置信息在硬盤尋找對應的命令,然後將其調入內存,最後再將其解釋為系統調用,提交給內核執行。

最後shell還是強大的解釋型程序設計語言,它定義了各種選項和變量,幾乎支持高級程序語言的所有程序結構,例如變量、函數、表達式和循環等。利用shell可以編寫shell腳本程序,類似於Windows/DOS下的批處理文件,但是shell功能更加完善,更加強大。

2:shell命令的語法分析

Linux下的各種shell的主要區別在於命令行的語法。對於一些普通的命令,各個shell版本的語法基本相同,只有在編寫一個shell腳本或者使用一些shell高級特性的時候,各個版本shell的差異才會顯示出來。

shell語法分析是指shell的對命令的掃描處理過程,也就是把命令或者用戶輸入的內容分解成要處理的各個部分的操作。在Linux系統下,shell語法分析包含很多的內容,例如重定向、文件名擴展和管道等。

這裏我們以bash為例,介紹以下shell命令的語法分析。

(1).shell的命令格式

用戶登錄系統後,shell命令行啟動。shell遵循一定的語法格式將用戶輸入的命令進行分析解釋並傳遞給系統內核。shell命令的一般格式為:

command  [options] [arguments]

根據習慣,我們一般把具有以上格式的字符串稱為命令行。命令行是用戶與shell之間對話的基本單位。

—  command:表示命令的名稱。

—  options:表示命令的選項。

—  arguments:表示命令的參數。

在命令行中,選項是包含一個或多個字母的代碼,主要用於改變命令的執行方式。一般在選項前面有一個“-”符號,用於區別參數。例如:

[root@WEBServer ~]#ls -a

ls命令加上-a選項後,列出當前目錄下的所有文件(包含隱藏文件)。如果ls不加“-a”選項,則僅僅顯示當前目錄下的文件名和目錄(不顯示隱藏文件)。

一般命令都有很多選項,可以單獨列出它們,也可以在“-”後面把需要的選項都列出來,例如,

ls –a –l

也可以寫成:

ls –al

很多命令都可以接受參數。參數就是在選項後面緊跟的一個或多個字符串,這些字符串指定了命令的操作對象,如文件或者目錄。例如,要顯示/etc目錄下的所有文件及信息,可用以下命令:

[root@WEBServer ~]#ls –al  /etc

特殊情況下,有些命令可以不帶參數,例如ls命令,而有些必須帶參數。當參數不夠時,shell就會給出錯誤提示。例如,mv命令至少需要兩個參數。

[root@WEBServer ~]#mv  mylinux1.txt  mylinux.txt

在shell的一個命令行中,還可以輸入多個命令,用分號將各個命令分開,例如:

[root@WEBServer ~]#ls –al;cp mylinux1.txt  mylinux2.txt

相反也可以在多行中輸入一個命令,用“\”將一個命令持續到下一行:

[root@WEBServer ~]#cp –i \

>mylinux1.txt \

> mylinux2.txt

(2).shell的通配符

通配符主要是為了方便用戶對文件或者目錄的描述,例如用戶僅僅需要以“.sh”結尾的文件時,使用通配符就能很方便地實現。各個版本的shell都有通配符,這些通配符是一些特殊的字符,用戶可以在命令行的參數中使用這些字符,進行文件名或者路徑名的匹配。shell將把與命令行中指定的匹配規則符合的所有文件名或者路徑名作為命令的參數,然後執行這個命令。

bash中常用的通配符有“*”、“?”、“[]”。

1)“*”——匹配任意一個或多個字符

例如:

[root@WEBServer ~]#ls *.txt

這個命令是列出當前目錄中所有以“.txt”結尾的文件(除去以“.”開頭的文件)。

[root@WEBServer ~]#cp doc/* /opt

表示將doc目錄下的所有文件(除去以“.”開頭的文件)拷貝到/opt目錄下。

[root@WEBServer ~]#ls –al /etc/*/*.conf

列出/etc目錄的子目錄下所有以“.conf”結尾的文件。在/etc目錄下的以“.conf”結尾文件將不會列出。

2)“?”——匹配任意單一字符

例如:

[root@WEBServer ~]#ls ab?.txt

將列出當前目錄下以ab開頭,隨後一個字母是任意字符,接著以“.txt”結尾的文件。

[root@WEBServer ~]#ls ab??.txt

將列出當前目錄下以ab開頭,隨後的兩個字母是任意字符,接著以“.txt”結尾的文件。

3)“[]”——匹配任何包含在方括號內的單字符

例如:

[root@WEBServer ~]#ls /dev/sda[12345]

/dev/sda1  /dev/sda2  /dev/sda3  /dev/sda4  /dev/sda5

上面列出了在/dev目錄下以sda開頭,第4個字符是1、2、3、4或5的所有文件。

[root@WEBServer ~]#ls /dev/sda[1-5]

在方括號中“1-5”給出了匹配的範圍,與上面一條命令完全等效。

4)通配符的組合使用

在Linux下,通配符也可以組合使用,例如:

[root@WEBServer ~]#ls [0-9]?.conf

列出當前目錄下以數字開頭,隨後一個是任意字符,接著以“.conf”結尾的所有文件。

[root@WEBServer ~]#ls [xyz]*.txt

列出當前目錄下以x、y或z開頭,最後以“.txt”結尾的文件。

(3).shell的重定向

Linux下系統打開3個文件,即標準輸入、標準輸出和標準錯誤輸出。用戶的shell將鍵盤設為默認的標準輸入,默認的標準輸出和標準錯誤輸出為屏幕。也就是用戶從鍵盤輸入命令,然後將結果和錯誤信息輸出到屏幕。

所謂的重定向,就是不使用系統默認的標準輸入輸出,而是重新指定,因此重定向分為輸入重定向、輸出重定向和錯誤輸出重定向。要實現重定向就需要了解重定向操作符,shell就是根據重定向操作符來決定重定向操作的。

1)輸入重定向

輸入重定向用於改變命令的輸入源,利用輸入重定向,就可以將一個文件的內容作為命令的輸入,而不從鍵盤輸入。

用於輸入重定向的操作符有“<”和“<<”。例如:

[root@WEBServer ~]#wc

53  229 1666

用wc命令統計輸入給它的文件/etc/inittab的行數、單詞數和字符數。

還有一種輸入重定向“<<”,這種重定向告訴shell,當前命令的標準輸入為來自命令行中一對分隔號之間的內容。例如:

[root@WEBServer ~]#wc << aa

> # Default runlevel. The runlevels used by RHS are:

> #   0 - halt (Do NOT set initdefault to this)

> #   1 - Single user mode

> #   2 - Multiuser, without NFS (The same as 3, if you do not have networking)

> #   3 - Full multiuser mode

> #   4 - unused

> #   5 - X11

> #   6 - reboot (Do NOT set initdefault to this)

> aa

8  65 303

上面的命令將一對分隔號aa之間的內容作為wc命令的輸入。分隔號可以是任意字符。shell將在第一個分隔號後開始讀取內容,直到出現另一個分隔號讀取結束,然後將內容送給wc命令處理。

2)輸出重定向

輸出重定向是將命令的輸出結果不在屏幕輸出,而是輸出到一個指定文件中。

在Linux下輸出重定向用得很多,例如,某個命令的輸出很長,一個屏幕無法顯示完畢,我們可以將命令的輸出指定到一個文件,然後用more命令查看這個文件,從而得到命令輸出的完整信息。

用於輸出重定向的操作符有“>”和“>>”。例如:

[root@WEBServer ~]#ps –ef >ps.txt

將ps –ef輸出的系統運行進程信息全部輸入到了ps.txt文件,而不輸出到屏幕,可以用more命令查看ps.txt文件中系統運行的進程信息。

[root@WEBServer ~]#more file1 file2 file3 >file

more命令是查看文件的內容,上面的命令是將file1、file2和file3的內容全部輸出到file文件中,類似於文件內容的合並。

如果在“>”後面指定的文件不存在的話,shell就會自動重建一個;如果文件存在的話,那麽這個文件原有的內容將被覆蓋;如果不想覆蓋存在的文件,可以使用“>>”操作符。例如:

[root@WEBServer ~]#ls –al /etc/* >>/root/install.log

將/etc目錄及其子目錄下的所有文件信息追加到/root/install.log文件的後面。/root/install.log文件原來的內容仍然存在。

3)錯誤重定向

錯誤重定向和標準輸出重定向一樣,可以使用操作符“2>”和“2>>”實現對錯誤輸出的重定向。例如:

[root@WEBServer ~]#tar zxvf text.tar.gz 2> error.txt

tar是打包命令,可以在屏幕上看到tar的解壓過程。如果“text.tar.gz”是個損壞的壓縮包,就會把錯誤信息輸出到error.txt文件。

(4).shell的管道

管道可以把很多命令連接起來,可以把第1個命令的輸入當作第2個命令的輸出,第2個命令的輸出當作第3個命令的輸入,依此類推。因此,管道的作用就是把一個命令的輸出當作下一個命令的輸入,而不經過任何中間文件。

通過管道符“|”可以建立一個管道連接,例如:

[root@WEBServer ~]# ls -al /etc/* |more

表示將/etc目錄以及子目錄下的所有文件分屏顯示。

[root@WEBServer ~]#ps -ef|grep httpd|wc –l

這個命令是查看系統中正在運行的httpd進程,並計算httpd的進程數。

(5).shell中的引用

在bash中有很多特殊字符,這些字符本身就具有特殊含義。如果在shell的參數中使用它們,就會出現問題。Linux中使用了“引用”技術來忽略這些字符的特殊含義,引用技術就是通知shell將這些特殊字符當作普通字符處理。shell中用於引用的字符有轉義字符“\”、單引號“'”、雙引號“" "”。

1)轉義字符“\”

如果將“\”放到特殊字符前面,shell就忽略這些特殊字符的原有含義,當作普通字符對待,例如:

[root@WEBServer ~]#ls

abc?*  C:\backup

[root@WEBServer ~]#mv abc\?\*  abc

[root@WEBServer ~]#mv C\:\\backup backup

上面是將abc?*重命令為abc,將C:\backup重命名為backup。因為文件名中含有特殊字符,所有都使用了轉義字符“\”。

2)單引號“'”

將字符串放到一對單引號之間,那麽字符串中所有字符的特殊含義將被忽略,例如:

[root@WEBServer ~]#mv C\:\\backup backup

[root@WEBServer ~]#mv 'C:\backup'  backup

上面兩條命令完全等效。

3)雙引號“" "”

雙引號的引用與單引號基本相同,包含在雙引號內的大部分特殊字符可以當作普通字符處理,但是仍有一些特殊字符即使用雙引號括起來,也仍然保留自己的特殊含義,比如“$”、“\”和“`”。

[root@WEBServer ~]#str="The \$SHELL Current shell is $SHELL"

[root@WEBServer ~]#str1="\$$SHELL"

[root@WEBServer ~]#echo $str

The $SHELL Current shell is /bin/bash

[root@WEBServer ~]#echo $str1

$/bin/bash

從上面輸出可以看出,“$”和“\”在雙引號內仍然保留了特殊含義。

[root@WEBServer ~]# str="This hostname is `hostname`"

[root@WEBServer ~]# echo $str

This hostname is WEBServer

上面的輸出中,字符“`”在雙引號中也保留了自己特殊含義。

(6).shell的自動補齊命令行

自動補齊命令行是bash一個簡單而且實用的功能,自動補齊命令行也就是在輸入命令時不必把命令輸全,shell就能智能判斷用戶所要輸入的命令。

當用戶輸入某個命令的一部分後,按下“Tab”鍵,shell就會根據系統環境變量信息提示出與用戶輸入命令相似的所有命令和文件,例如:

[root@WEBServer ~]# if <按Tab鍵>

if    ifcfg    ifconfig   ifdown    ifenslave  ifnames    ifrename   ifup

[root@WEBServer ~]# if

可以從上面看到,用戶輸入“if”後按“Tab”鍵,即可顯示以“if”為前綴的所有命令和文件。如果需要的是ifconfig命令,那麽只需再次輸入“co”,然後按“Tab”鍵,shell就能補全命令。
全站分類:知識學習 科學百科
自訂分類:不分類
上一則: C/C++內存的理解
下一則: Linux內核中常見內存分配函數
你可能會有興趣的文章:

限會員,要發表迴響,請先登入