shell編程學習(一)

shell歷史

Shell的作用是解釋執行用戶的命令,用戶輸入一條命令,Shell就解釋執行一條,這種方式稱爲交互式(Interactive),Shell還有一種執行命令的方式稱爲批處理(Batch),用戶事先寫一個Shell腳本(Script),其中有很多條命令,讓Shell一次把這些命令執行完,而不必一條一條地敲命令。Shell腳本和編程語言很相似,也有變量和流程控制語句,但Shell腳本是解釋執行的,不需要編譯,Shell程序從腳本中一行一行讀取並執行這些命令,相當於一個用戶把腳本中的命令一行一行敲到Shell提示符下執行。

由於歷史原因,UNIX系統上有很多種Shell

1.      shBourne Shell):由SteveBourne開發,各種UNIX系統都配有sh

2.      cshC Shell):由Bill Joy開發,隨BSD UNIX發佈,它的流程控制語句很像C語言,支持很多BourneShell所不支持的功能:作業控制,命令歷史,命令行編輯。

3.      kshKorn Shell):由David Korn開發,向後兼容sh的功能,並且添加了csh引入的新功能,是目前很多UNIX系統標準配置的Shell,在這些系統上/bin/sh往往是指向/bin/ksh的符號鏈接。

4.      tcshTENEX CShell):是csh的增強版本,引入了命令補全等功能,在FreeBSDMacOS X等系統上替代了csh

5.      bashBourne AgainShell):由GNU開發的Shell,主要目標是與POSIX標準保持一致,同時兼顧對sh的兼容,bashcshksh借鑑了很多功能,是各種Linux發行版標準配置的Shell,在Linux系統上/bin/sh往往是指向/bin/bash的符號鏈接。雖然如此,bashsh還是有很多不同的,一方面,bash擴展了一些命令和參數,另一方面,bash並不完全和sh兼容,有些行爲並不一致,所以bash需要模擬sh的行爲:當我們通過sh這個程序名啓動bash時,bash可以假裝自己是sh,不認擴展的命令,並且行爲與sh保持一致。

itcast$ vim /etc/passwd

    其中最後一列顯示了用戶對應的shell類型

    root:x:0:0:root:/root:/bin/bash

    nobody:x:65534:65534:nobody:/nonexistent:/bin/sh

    syslog:x:101:103::/home/syslog:/bin/false

    itcast:x:1000:1000:itcast,,,:/home/itcast:/bin/bash

    ftp:x:115:125:ftp daemon,,,:/srv/ftp:/bin/false

用戶在命令行輸入命令後,一般情況下Shellforkexec該命令,但是Shell的內建命令例外,執行內建命令相當於調用Shell進程中的一個函數,並不創建新的進程。以前學過的cdaliasumaskexit等命令即是內建命令,凡是用which命令查不到程序文件所在位置的命令都是內建命令,內建命令沒有單獨的man手冊,要在man手冊中查看內建命令,應該執行

itcast$ manbash-builtins

exportshiftifeval[forwhile等等。內建命令雖然不創建新的進程,但也會有Exit Status,通常也用0表示成功非零表示失敗,雖然內建命令不創建新的進程,但執行結束後也會有一個狀態碼,也可以用特殊變量$?讀出。

執行腳本

編寫一個簡單的腳本test.sh

#! /bin/sh

cd ..

ls

Shell腳本中用#表示註釋,相當於C語言的//註釋。但如果#位於第一行開頭,並且是#!(稱爲Shebang)則例外,它表示該腳本使用後面指定的解釋器/bin/sh解釋執行。如果把這個腳本文件加上可執行權限然後執行:

itcast$ chmod a+xtest.sh

itcast$ ./test.sh

Shellfork一個子進程並調用exec執行./test.sh這個程序,exec系統調用應該把子進程的代碼段替換成./test.sh程序的代碼段,並從它的_start開始執行。然而test.sh是個文本文件,根本沒有代碼段和_start函數,怎麼辦呢?其實exec還有另外一種機制,如果要執行的是一個文本文件,並且第一行用Shebang指定了解釋器,則用解釋器程序的代碼段替換當前進程,並且從解釋器的_start開始執行,而這個文本文件被當作命令行參數傳給解釋器。因此,執行上述腳本相當於執行程序

itcast$ /bin/sh./test.sh

以這種方式執行不需要test.sh文件具有可執行權限。

如果將命令行下輸入的命令用()括號括起來,那麼也會fork出一個子Shell執行小括號中的命令,一行中可以輸入由分號;隔開的多個命令,比如:

itcast$ (cd ..;ls -l)

和上面兩種方法執行Shell腳本的效果是相同的,cd..命令改變的是子ShellPWD,而不會影響到交互式Shell。然而命令

itcast$ cd ..;ls -l

則有不同的效果,cd ..命令是直接在交互式Shell下執行的,改變交互式ShellPWD,然而這種方式相當於這樣執行Shell腳本:

itcast$ source ./test.sh

或者

itcast$ . ./test.sh

source或者.命令是Shell的內建命令,這種方式也不會創建子Shell,而是直接在交互式Shell下逐行執行腳本中的命令。

發佈了19 篇原創文章 · 獲贊 2 · 訪問量 9890
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章