進度 計算機概論與硬體知識 網路基礎知識 安裝與指令 作業系統的基礎技能 vi文書編輯器 Shell與Shell Script 軟體管理 (安裝 & 維護) 2018/11/22
Shell Script http://linux.vbird.org/linux_basic/0320bash.php
Shell 介於作業系統與系統核心之間的仲介程式就是所謂的 Shell 不同的作業系統都有其適用的 Shell 常見的Shell 包括: Bourne shell 其可執行檔名為 sh,為UNIX的標準配備,也是root所預設的shell C shell其可執行檔名為csh,通常位於/bin/csh底下,其首創之舉為工作排程式控制,指令歷史和別名(alias)的功用 Korn shell可執行檔檔名為ksh,其在程式的設計方面是使用Bourne shell的語法,又加上了tcsh的alias、job controll、指令列編輯等等優點 Bourne Again shell可執行檔檔名為bash。通常放在/bin/bash底下,基本上他是前面數種 shell 的融合,是GNU的產品 etc
認識Shell 目前以 bash 較為普遍,Ubuntu Linux 便是採用 bash
前言 JavaScript、VBScript 等, 都是屬於 script 語言 此種語言的特色是不需要事先編譯,而在需要執行時才直接解譯每一行程式的內容 在 Linux 上的 Perl、Python 等都是這一類的語言,而用這些語言所撰寫的程式,則稱為 script shell script,則是指用使用者環境 shell (例如 bash) 所提供的語法所撰寫的 script
前言 Unix 指令可分為系統指令和 shell 指令,其中系統指令是指 ls、cat、rm 等等我們在先己經介紹過的指令 而 shell 指令是指由 shell 直接解譯的指令,通常用於 script 檔程式流程的控制, 像是分支 (case...)、迴圈 (loop...) 或判斷 (if...) 等用途
系統 和 shell 指令? 如何判斷? Use “type”
前言 如果您時常用到相同執行順序的操作指令時, 便可將這些指令寫成 script 檔,如此往後要做同樣的事情時,只要在指令列輸入該 script 檔名執行即可,如此能省時省力 Shell script 具有接受指令列參數、使用者輸入/輸出及設定變數的能力
什麼是 Shell Script? shell 不僅可以下達單一的指令對於Linux 系統進行操作,例如複製檔案、刪除檔案,建立目錄等等 亦可程式化、批次化 經由程式語言的輔助,將原本複雜的、重複的系統指令綜合成批次指令,達到簡化與自動化的目的
建立及執行 Shell Script Echo 指令及變數名稱可以直接顯示指定變數的資料值 環境變數隨著所採用的 Shell 不同會有所差異,以Bash 為例,可能之環境變數包括:
環境變數? 系統指令【export】可列出當前的所有環境變數
建立及執行 Shell Script 以一個簡單的範例, 來介紹如何建立與執行 shell script 此範例會顯示目前的日期時間、執行路徑、使用者帳號及所在的目錄位置 建立 Shell Script 1 執行 Shell Script 2
建立 Shell Script 請以 man 了解 echo 指令後,再依序執行下圖紅色框框內之指令… (一會兒請您分享喔)
建立 Shell Script `whoami` 字串左右的反引號 (`) 是用做指令置換,也就是將它所括起來的字串視為指令執行,並將其輸出字串在原地展開 `date` 之意義也是一樣
建立 Shell Script 請在文書編輯器 vi 編輯下列檔案內容 (紅色框框內),並存檔為 showinfo
建立 Shell Script script 檔名不可設為 test,因為 test 是一個系統指令,這可能會造成非預期的執行結果 第 1 行 “#!/bin/bash” 是用來指定此 script 以 bash 執行,如果要設定以 tcsh 執行,則應設成 “#!/bin/tcsh” 一定要將它寫在第 1 行 第 2 行之 “#” 則為註解,在 script 執行時會略過
執行 Shell Script 執行 shell script 的方式有 2 種,一種是執行 shell 程式,並將該 script 當作參數傳給它
執行 Shell Script 另一種方式是在指令列下直接輸入 script 檔名執行 須先將檔案權限更改成可執行的權限,否則 … Why “$./showinfo”? Why not “$showinfo”? 這跟 PATH 參數有關
Command not found? PATH ?
Command not found?
設定與取用變數的方法 變數,就是可存放資料的 identifier 在 shell script 中設定與取用變數的方法包括: E.g., x=10, x 是個變數名稱、10則 為存放的資料 在 shell script 中設定與取用變數的方法包括: 直接設定變數值 由指令置換取得 由指令列參數取得 由環境變數取得 由使用者輸入
直接設定變數值 例如,建立一個 user_age 變數存放使用者的年齡、或設定 100 給 fare 這個變數 = 兩邊不能有空白
由指令置換結果取得變數值 就是把指令執行的結果設定為某一個變數的變數值
使用指令列參數 執行 script 檔時, 可以加上一些參數傳入 script 中運算 以下變數即可用來讀取指令列所輸入的參數
使用指令列參數
使用環境變數 系統中有許多內定的環境變數,也有許多由其他程式所輸出 (export) 的環境變數,這些變數也可以在 script 檔中直接取用
由使用者輸入 使用 read 指令可以直接讀取使用者的輸入作為變數值,可以用來撰寫對話式的 shell script。以下範例會先列出要求輸入使用者姓名的字串, 待使用者輸入姓名後, 將輸入的字串讀入並設定為 my_name 變數的值, 使用者輸入完並按下 [Enter] 鍵後, 顯示 "My name is" 及 my_name 變數的值 (即使用者輸入的字串):
由使用者輸入
建構 Shell Script 條件測試與運算式 程式流程控制 移動輸入參數 定義及使用函數
條件測試與運算式 test 指令用來判斷運算式的真假 (True 或 False), 其語法為: test 指令還有另外一種表達方式, 即是以中括號括住所要判斷的運算式, 如 "[ 運算式 ]"。使用這種表達方式時, 於運算式前不必加上 "test" 識別字。請在指令列執行以下範例 (等號兩邊要有一個空格): man test
條件測試與運算式
條件測試與運算式 test 指令常用於 if 及 while 敘述等迴圈結束條件的測試, 它能測試的運算式可分成 『字串』、『數值』、『檔案』 與 『邏輯』 等 4 類 每一類的運算式各有其適用的運算子, 以下分項列表說明。
條件測試與運算式 字串運算子 數值運算子 檔案運算子 邏輯運算子
字串運算子 字串運算子用來判斷字串運算式的真偽。可用的運算子如下表:
字串運算子 字串運算子不可使用萬用字元, 同時應注意運算子的左右需留空白。 以下為執行範例:
數值運算子 數值運算子用來判斷數值運算式的真偽。 可用的運算子如下表 (其中 int1及 int2 為整數):
數值運算子 如果您將數值運算子用於一般字串, 將得到錯誤訊息。以下為執行範例:
檔案運算子 檔案運算子用來判斷檔案是否存在, 以及檔案形態和屬性。可用的運算子如下表: -d file -f file -s file -r file -w file -x file
檔案運算子 以下為執行範例:
邏輯運算子 邏輯運算子用來結合運算式或取得運算式的相反值。可用的運算子如下表:
邏輯運算子 以下為執行範例:
程式流程控制 if 敘述 case 敘述 for 敘述 while 敘述及 until 敘述 break 子句及 continue 子句
if 敘述 if 敘述可根據運算式的真偽值, 決定要執行的程式段落。其語法如下:
if 敘述 fi 是 if 敘述的結束符號 (剛好是 if 倒過來), 必須與 if 成對出現, 而 elif 及 else子句可有可無。elif 是 else if 的簡寫, 當 if 的運算式不成立時, 才會接著測試 elif的運算式。如果 if 及 elif 的測試條件皆不成立, 最後才會執行 else 子句內的指令。一個 if 可以有好幾個 elif 子句, 但只能有一個 else 子句。以下範例將顯示目錄內是否有 readme 檔案:
if 敘述
case 敘述 case 敘述用來從許多的測試條件中選擇第 1 個符合的條件執行。其語法如下:
case 敘述 case 敘述適用於字串的比較, 其測試條件可用萬用字元。雙分號 (;;) 為測試條件的結束符號, 在每一個測試條件成立後, 一直到雙分號之前的指令, 都會被 shell所執行。 使用萬用字元作為測試條件時, 請勿於字串左右加上雙引號 (" "), 因為如此將使字串無法正確匹配。
case 敘述 由於所有字串都可與萬用字元 * 匹配, 因此 *) 之後的指令可視為 case 敘述預設的執行指令。 底下示範如何寫一個簡單的安裝程式, 請將檔名取為 install:
case 敘述
case 敘述
case 敘述 由於此為安裝程式, 故需要以 root 權限執行, 以下為執行範例:
for 敘述 for 敘述可以對串列中的每一個元素執行相同的指令。有 2 種語法:
for 敘述 或 在 shell script 中的串列是指由空白符號所分隔的字串。
for 敘述 由第二種語法的定義可知它是第一種語法的簡寫, 亦即當 for 敘述未使用 in 子句時, 即代表使用參數列作為預設串列, 因此底下兩個敘述的功用是相同的:
for 敘述 for 敘述的 in 子句與 case 敘述的 in 子句一樣, 可使用萬用字元。 底下範例程式會顯示目錄中所有 .txt 的文字檔案名稱及內容:
while 敘述及 until 敘述 while 敘述與 until 敘述的語法結構和用途類似, while 敘述會在測試條件為真時重複執行。語法如下:
while 敘述及 until 敘述 而 until 敘述會在其測試條件為假時重複執行。其語法如下:
break 子句及 continue 子句 在 shell 的 for、while、until 迴圈敘述中也可以使用如 C 語言的 break 及continue 子句以跳脫現有的迴圈。 break 子句用於中斷迴圈的執行, 將程式流程移至迴圈敘述結束之後的下一個指令。 continue 子句則在忽略子句之後的指令, 將程式流程移至迴圈開始的地方。
break 子句及 continue 子句 break 子句及 continue 子句都可加上數字參數, 以指示要跳脫的迴圈數目, 例如以下的 continue 子句將跳脫 2 層迴圈:
break 子句及 continue 子句 以下範例程式檔名為 jobcontrol, 用來模擬工業上的作業流程控制:
break 子句及 continue 子句
break 子句及 continue 子句 修改檔案權限後, 即可於指令列輸入 bash jobcontrol 指令自行測試。
移動輸入參數 shift 指令用來將指令列參數向左移。假設指令列的 3 個參數如下: 則在執行 shift 指令之後, 其值會變成:
移動輸入參數 shift 指令常與 while 敘述或 until 敘述合用, 底下的範列示範如何將一個檔案中的小寫英文字母全部轉為大寫字母, 筆者將其存成 upcase 檔(此 shell script將使用 "-i" 參數指定來源檔案, 使用 "-o" 參數指定輸出後的目的檔案) :
移動輸入參數
移動輸入參數 上例中的 tr 指令會讀取第 1 個參數所設定的檔案, 轉換字元後寫到第 2 個參數所設的檔案。以下是執行結果:
移動輸入參數
定義及使用函數 Shell script 也有自訂函數的功能。當 script 檔案變得很大時, 我們可以將script 檔案中常用的指令程序寫成函數, 如此會使 script 更易於維護並更具結構性。定義函數的語法如下:
定義及使用函數 函數的使用方式與外部指令一樣, 只要直接使用函數的名稱即可。在使用函數時, 一樣可以傳入參數。函數處理參數的方式與 script 檔處理指令列參數的方式是一樣的。在函數中, $1 是指傳入函數的第 1 個參數, $2 是指傳入函數的第 2 個參數...。同時也可以使用 shift 指令來移動函數參數。
定義及使用函數 底下範例示範如何將指令列輸入的數字傳入函數中, 並顯示最大的數值。 筆者將檔名取為 maxvalue:
定義及使用函數
定義及使用函數 在上例中, 筆者為了說明如何取得函數的傳回值而使用了 $? 及 return 指令。一個比較常用的作法是直接取用 $maxvalue 的值, 在 scrpit 中變數值並不會因為函數結束而消失。 範例執行結果如下:
輸出環境變數 在之前的內容曾提到, 我們可以直接將環境變數作為 script 檔的預設變數使用。其實也可以將 script 檔中的自訂變數輸出成環境變數, 方法是使用 export 指令及 source 指令。 export 指令能將 script 檔內的變數輸出給其他的指令使用, 其方法如下:
輸出環境變數 在一般的情況下執行 script 時, 系統會產生一個新的 shell 程式來執行它,其過程如下圖所示:
輸出環境變數
輸出環境變數 如上圖所示, 就算在 script 檔中有用 export 指令輸出環境變數, 也會隨著該shell 程式的結束而消失。 要使環境變數存留於目前的 shell 中, 則必須使用 source 指令執行該 script。其語法如下:
輸出環境變數 以 source 指令執行 script 程式時, 系統並不會產生新的 shell 程式, 而是以目前的 shell 環境來執行:
輸出環境變數
輸出環境變數 由此可見, 以 source 指令執行 script 程式,可使該檔中所 export 的變數存留在 shell 中,而成為環境變數。 此外, 在 bash 中可以使用 . 指令來取代 source 指令, 以下兩個指令的功能相同: