五個鮮為人知的現代 Bash 腳本編寫技術
程序員經常使用Bash命令語言創建Shell腳本來自動化手動任務。例如,他們會為各種配置、文件操作、生成構建結果和各種與DevOps相關的活動創建Bash腳本。幾乎所有類Unix或基于Unix的操作系統都為用戶提供預安裝的Bash解釋器,因此我們可以使用Bash編寫更具可移植性的自動化腳本。
正如我們已經知道的那樣,Bash腳本編寫是指使用Bash命令語言的語法、內置Bash命令和核心操作系統CLI程序(如GNU核心工具)編寫一系列命令。標準且老式的Bash腳本通常執行一些命令并在終端上顯示純文本輸出。
然而,我們可以通過幾個獨特的概念使我們的Bash腳本更具未來性和用戶友好性。以下概念通過一些鮮為人知的現代Bash腳本編寫技術,使您的自動化腳本更加現代化。
顯示動畫以指示長時間運行的任務
在某些情況下,我們需要從Bash腳本中執行長時間運行的命令。有幾種方法可以指示長時間運行的任務。最簡單和最容易的方法是使用echo命令顯示帶有三個尾隨點(也稱為省略號)的消息。但是,這種方法產生的是一個靜態消息,對用戶和開發人員來說不是很交互式和友好。
我們可以使用核心Unix操作系統命令和Bash內置命令輕松顯示ASCII動畫。看下面這個只有兩個動畫幀的簡單動畫示例:
#!/bin/bash
# Linux迷 www.linuxmi.com
while true;
do
# Frame #1
printf "\r< Loading..."
sleep 0.5
# Frame #2
printf "\r> Loading..."
sleep 0.5
done
上面的Bash腳本在終端上顯示一個無盡的兩幀動畫。printf語句使用\r轉義字符來重置當前行的終端光標。上面的腳本呈現了以下基于文本的動畫:
一個簡單的兩幀文本動畫
我們可以在動畫中添加更多幀,并使用以下Bash腳本在特定耗時任務完成之前一直顯示動畫。
#!/bin/bash
# Linux迷 www.linuxmi.com
sleep 5 &
pid=$!
frames="/ | \\ -"
while kill -0 $pid 2&>1 > /dev/null;
do
for frame in $frames;
do
printf "\r$frame Loading..."
sleep 0.5
done
done
printf "\n"
上面的腳本顯示一個基于文本的旋轉器動畫,直到sleep 5命令完成執行。類似地,我們可以在任何耗時任務中顯示旋轉器動畫,而不是用echo顯示靜態消息。預覽如下。
一個帶有旋轉器文本動畫的Bash腳本,作者的截圖 這些基于文本的動畫使命令行程序更加用戶友好和互動,因此大多數現代命令行程序都顯示這些ASCII動畫。現在,你知道如何通過改變幀字符列表來使你的Bash腳本也具有動畫效果了。
從Bash顯示本地GUI通知
Bash腳本和命令行程序通常為經常使用終端界面的開發人員提供工具。例如,Flutter框架為開發人員提供了flutter命令行程序,用于管理Flutter應用程序和配置Flutter應用程序開發環境。假設你正在開發一個耗時的命令行腳本。在用戶不查看終端輸出時,如何顯示重要消息?
所有類Unix和基于Unix的操作系統都有特殊的命令來顯示GUI通知。我們可以從Bash腳本中調用這些命令來顯示本地通知。例如,你可以在基于GNU/Linux的操作系統上使用notify-send命令,如下所示。
#!/bin/bash
# Linux迷 www.linuxmi.com
sleep 10
notify-send "notify.sh" "Task #1 已成功完成 www.linuxmi.com"
一些GNU/Linux發行版通常會預裝notify-send工具的版本。上面的Bash腳本在十秒后顯示了一個本地通知。預覽如下:
在Ubuntu上的本地通知截圖
macOS用戶可以通過在Bash中執行AppleScript解釋器來顯示本地通知,如下所示:
#!/bin/bash
sleep 10
osascript -e "display notification \"Task #1 www.linuxmi.com 已成功完成\" with title \"notify.sh\""
在Bash腳本中的多進程處理非常有助于通過長時間運行的腳本或永久運行的后臺腳本向用戶通知重要事件。
在Bash腳本中的多進程處理
通常,程序員使用Bash腳本按順序運行命令。因此,Bash解釋器會逐個執行每個語句,直到達到源文件的末尾或遇到exit語句。然而,我們可以改變這種順序執行的方式,實現并行執行以加快自動化腳本的速度。
首先,我們可以將整個Bash腳本分解為幾個獨立的函數,可以異步運行每個函數。接下來,我們可以將所有Bash函數作為后臺任務運行。最后,我們可以使用內置的wait命令來保持腳本執行過程處于活動狀態,直到所有異步進程執行結束。
請看以下示例代碼:
#!/bin/bash
# Linux迷 www.linuxmi.com
function task1() {
echo "Running task1..."
sleep 5
}
function task2() {
echo "Running task2..."
sleep 5
}
task1 &
task2 &
wait
echo "www.linuxmi.com 全部完成"
在這個例子中,我們將兩個并行函數task1和task2作為后臺任務運行。此外,我們使用內置的wait命令使腳本實例保持活動狀態,直到后臺任務完成執行。如果你檢查腳本的執行時間,你會發現這兩個函數在大約五秒鐘內結束,而不是十秒鐘。
使用Bash顯示GUI組件
前面我們討論了如何通過長時間運行的Bash腳本顯示GUI通知。類似地,我們可以顯示其他GUI組件,如消息框、輸入框和文件選擇對話框。有時我們需要為非技術人員創建基于GUI的自動化程序。如果你已經了解Bash腳本編寫,你不需要使用其他GUI開發工具來創建簡單的GUI應用程序——因為我們可以使用Bash顯示GUI元素。
zenity程序提供了幾個命令,用于在GNU/Linux命令行環境中顯示各種GUI元素。例如,我們可以使用以下命令打開文件選擇對話框。
zenity --file-selection
大多數基于GNOME的GNU/Linux操作系統發行版都預裝了Zenity版本。此外,作為替代,你可以在基于KDE的GNU/Linux發行版中使用kdialog命令。
macOS用戶可以像往常一樣調用AppleScript解釋器。例如,他們可以使用以下命令通過Bash腳本顯示文件選擇對話框。
osascript -e "POSIX path of (choose file)"
你也可以像Zenity那樣構建自己的二進制文件,并從Bash腳本中顯示任何GUI組件。此外,你還可以使用Neutralinojs通過Bash腳本在本地/遠程窗口中顯示交互式的HTML界面。
使用文本樣式現代化終端輸出
我們經常使用echo命令輸出腳本中的消息。默認情況下,echo命令根據默認終端文本樣式打印給定的文本。但是,在某些情況下,我們可以通過使用基本的用戶體驗原則根據當前上下文改進文本樣式。例如,我們可以使用紅色顯示錯誤消息。此外,您可以使用粗體字體樣式強調段落中的一些關鍵細節。
tput是一個Unix程序,提供控制當前終端屏幕的命令。它提供了改變終端光標位置、獲取終端信息和更改文本樣式的命令。我們可以將tput命令與echo命令結合使用,在所有類Unix和基于Unix的操作系統上打印各種文本樣式。
請看以下示例,打印不同的文本樣式:
#!/bin/bash
# Linux迷 www.linuxmi.com
bold=$(tput bold)
underline=$(tput smul)
italic=$(tput sitm)
info=$(tput setaf 2)
error=$(tput setaf 160)
warn=$(tput setaf 214)
reset=$(tput sgr0)
echo "${info}INFO${reset}: This is an ${bold}info${reset} message"
echo "${error}ERROR${reset}: This is an ${underline}error${reset} message"
echo "${warn}WARN${reset}: This is a ${italic}warning${reset} message"
在這里,我們使用tput命令為每種文本樣式定義了一些變量。最后,我們使用echo命令執行臨時保存的命令,以顯示不同的文本樣式,如下所示。
Bash中的文本樣式屏幕截圖
您可以使用上述方法為Bash腳本構建自己的個性化顏色方案。上面的示例腳本使用空設備文件(/dev/null)來隱藏kill命令的錯誤消息。