跳轉到內容

Shell 程式設計/特性

來自 Wikibooks,開放的書籍,開放的世界


作為程式語言,shell 通常具有非常有限的特性:它們的主要功能來自於呼叫外部命令。

但是,有一些特性非常強大,而且在其他語言中不常見或不太為人所知。

  • 流、管道和重定向
  • 程序管理
  • 陷阱

這些特性在多核系統上特別有用,因為程序通常可以並行執行。

流允許在不需要一次讀取所有資料的情況下,對任意大量資料(codata)進行操作,逐步讀取輸入或寫入輸出;最基本的流是標準輸入和標準輸出。最簡單的方法是逐行操作文字資料。管道允許將一個程式的輸出流連線到另一個程式的輸入流,允許對資料進行併發處理。許多標準的Unix 命令對流進行操作,特別是用於文字處理,並設計用於管道中 - 這些命令有時被稱為過濾器。shell 指令碼的標準慣用語是構建一個管道,將這些命令連線起來,以快速構建複雜且相對高效的程式。

除了匿名管道之外,命名管道(也稱為 FIFO)還允許複雜的程序間通訊 (IPC);請參閱NamedPipes

程序管理

程序管理允許非同步(不阻塞)執行和控制多個程序。如果一個命令以&結尾,則該程序將在後臺執行(立即執行到下一個命令)。請注意,&是一個命令分隔符,就像;一樣 - 您可以類似地寫a & b就像a; b一樣,您永遠不需要寫&;

shell 可以管理程序 - 通常只應該管理其自己的子程序 - 儘管實際上只有有限的設施是可行的。

  • 等待一個或多個程序完成:透過wait,它可以接受多個程序 ID;
  • 終止一個程序,透過kill
  • 檢查一個程序的狀態,透過kill -0

但是,shell 無法訪問 select(2) 或 poll(2),因此它們無法等待一組程序中的一個程序完成;這嚴重限制了可以執行的操作。

原則上,也可以向程序傳送其他訊號,但這非常罕見。請參閱ProcessManagement 以獲取詳細的資訊。

要簡單地在並行執行多個程序,請使用帶有-P標誌的xargspexec,或者更簡潔地使用GNU parallelsem 通常很有用)。

啟動一個連線的程序(及其子程序)的管道會建立一個程序組 - 程序組 ID 是引導程序的程序 ID,最初是管道中的最後一個程序,可以使用帶有負引數的 kill 向整個程序組傳送訊號(記住--,因此它不會被解釋為標誌!):kill 123 終止程序 123,kill -- -123 終止程序 123。pkill 和 pgrep 允許透過不同的欄位選擇程序,例如父程序 ID 或程序名稱(不推薦,因為易碎)。要從程序中獲取程序組 ID,請使用ps。請注意,沒有簡單的方法可以引用“一個程序及其後代”(pgrep/pkill 允許您透過父程序進行選擇,從而找到直接的子程序,但這些子程序沒有遞迴選項),因此終止或向所有後代(但不包括整個程序組)傳送訊號很棘手 - 請參閱“終止所有子程序的最佳方法”。

請注意,shell 通常也包含“作業”的概念,其中“作業”是引用程序組的簡寫(通常是從 1 開始的數字),由 fg 和 bg 命令使用。這通常只對互動式會話有用 - 對於使用程序組 ID(或只是程序 ID)的指令碼來說,更簡單且更健壯。程序/程序組(OS)和作業(shell)的概念很容易混淆,因此程序管理通常被稱為作業控制,即使它不是互動式的。

陷阱

作為傳送訊號的補充,shell 指令碼可以使用trap接收來自其他程序的訊號,並設定處理程式來響應它們。這些主要用於執行時間更長的指令碼,主要是守護程序(後臺程序),允許它們被幹淨地終止、重新載入、掛起或恢復。這主要用於在收到 KILL 時清理,或在收到 HUP 時重新載入配置。其他可以有用地捕獲的訊號包括 TSTP(當作業被 shell 掛起或“停止”時)和 CONT(當作業被恢復或“繼續”時) - 這允許顯式掛起和繼續處理程式。請參閱SignalTrap: 傳送和捕獲訊號 以獲取詳細資訊。

華夏公益教科書