如果你厭倦了執行時間過長的 Bash 腳本,這份教程就是為你而來的。通常,你可以使用 GNU Parallel 實用程式,也被簡稱為 Parallel,並結合一些方便的 GNU Parallel 示例,以並行執行 Bash 腳本,從而顯著提高執行速度。如何實現呢?使用 GNU Parallel 實用程式,這裡有一些實用的 GNU Parallel 示例!
Parallel 通過一個稱為多線程的概念,並行執行 Bash 腳本。此實用程式允許你在每個 CPU 上運行不同的作業,而不僅僅是一個,從而縮短運行腳本的時間。
在這份教程中,你將學到如何使用許多出色的 GNU Parallel 示例實現 Bash 腳本的多線程處理!
先備條件
這個教程將充滿實際演示。如果你打算跟隨進行,請確保你擁有以下內容:
- A Linux computer. Any distribution will work. The tutorial uses Ubuntu 20.04 running on Windows Subsystem for Linux (WSL).
- 以具有 sudo 權限的使用者登錄。
安裝 GNU Parallel
為了加快 Bash 腳本的多線程處理,你首先需要安裝 Parallel。所以讓我們開始下載並安裝它。
1. 開啟 Bash 終端機。
2. 執行 wget
下載 Parallel 套件。下面的命令將最新版本 (parallel-latest
) 下載到當前工作目錄。
如果您寧願使用舊版的GNU Parallel,您可以在官方下載網站找到所有的套件。
3. 現在,執行下面的tar命令來解壓縮您剛下載的套件。
下面的命令使用x
標誌來解壓縮存檔,j
指定目標存檔的擴展名為.bz2
,f
接受一個文件作為tar命令的輸入。sudo tar -xjf parallel-latest.tar.bz2
您現在應該有一個以最新發行日期命名的目錄parallel-。
4. 使用cd
進入套件存檔文件夾。在本教程中,套件存檔文件夾被稱為parallel-20210422,如下所示。

5. 接下來,運行以下命令構建並安裝GNU Parallel二進制文件:
現在,通過檢查安裝的版本來驗證Parallel是否正確安裝。

第一次運行Parallel時,您可能還會看到一些顯示類似
perl: warning:
的嚇人行的文本。這些警告信息表明Parallel無法檢測到您當前的區域設置和語言設置。但暫時不要擔心這些警告。稍後您將學習如何修復這些警告。
配置GNU Parallel
現在已經安裝了 Parallel,您可以立即使用它!但在開始之前,先配置一些重要的細微設置。
在您的 Bash 終端中,同意 GNU Parallel 的 學術研究許可,通過指定 citation
參數後跟著 will cite
,告訴 Parallel 您將在任何學術研究中引用它。
如果您不想支持 GNU 或其維護者,同意引用並非使用 GNU Parallel 的必要條件。
通過執行下面的代碼行來更改區域設置的 環境變數。像這樣設置區域和語言環境變數並不是必需的,但 GNU Parallel 每次運行時都會檢查它們。
如果環境變數不存在,Parallel 將在每次運行時投訴它們,就像您在前一節中看到的那樣。
本教程假設您是英語使用者。也支援其他 語言。

運行即時殼層命令
讓我們現在開始使用 GNU Parallel!首先,您將學習基本的語法。一旦您熟悉了語法,您將進入一些方便的 GNU Parallel 實例。
為了開始,讓我們講解一個非常簡單的例子,只是回顧數字 1 到 5。
1. 在您的 Bash 終端中,運行以下命令。令人興奮,不是嗎?Bash 使用echo 命令將數字 1 到 5 發送到終端。如果您將這些命令放入腳本中,Bash 將按順序執行每個命令,等待前一個完成。
在此示例中,您正在執行五個幾乎不需要時間的命令。但是,想象一下如果這些命令是實際執行某些有用但運行時間很長的 Bash 腳本會怎樣呢?
現在,使用 Parallel 同時運行每個命令,如下所示。在此示例中,Parallel 運行 echo 命令,由:::
指定,將該命令的參數1
,2
,3
,4
,5
傳遞給它。三個冒號告訴 Parallel 您正在通過命令行而不是管道提供輸入(稍後會更多)。
在下面的示例中,您對 Parallel 傳遞了一個不帶任何選項的單個命令。在這裡,就像所有 Parallel 示例一樣,Parallel 為每個命令啟動了一個新的進程,使用不同的 CPU 核心。
所有 Parallel 命令都遵循語法
parallel [選項] <多線程命令>
。
3. 為了展示從 Bash pipeline 接收輸入並行的情況,請創建一個名為 count_file.txt 的文件,其內容如下。每個數字代表您將傳遞給 echo 命令的參數。
4. 現在,運行 cat
命令讀取該文件並將輸出傳遞給 Parallel,如下所示。在此示例中,{}
代表將傳遞給 Parallel 的每個參數(1-5)。

比較 Bash 和 GNU Parallel
現在,使用 Parallel 可能只是運行 Bash 命令的一種複雜方式。但對您真正的好處是節省時間。請記住,Bash 只能在一個 CPU 核心上運行,而 GNU Parallel 可以同時在多個核心上運行。
1. 為了展示順序 Bash 命令與 Parallel 之間的差異,請創建一個名為 test.sh 的 Bash 腳本,代碼如下。請在之前創建 count_file.txt 的相同目錄中創建此腳本。
下面的 Bash 腳本讀取 count_file.txt 文件,休眠 1、2、3、4 和 5 秒,將休眠時間回顯到終端並終止。
2. 現在,使用time
命令運行腳本,以測量腳本完成所需的時間。它將花費 15 秒。
3. 現在,再次使用time
命令執行相同的任務,但這次使用 Parallel 來執行。
以下命令執行相同的任務,但這次不是等待第一個循環完成後再開始下一個,而是在每個 CPU 核心上運行一個,並在同一時間開始盡可能多的任務。

了解乾跑!
現在是時候了解一些更真實的 GNU Parallel 示例了。但在開始之前,您應該先了解--dryrun
標誌。當您想查看 Parallel 實際執行情況時,此標誌非常方便。
--dryrun
標誌可以在執行命令之前進行最後的健全性檢查,以確保命令的行為符合您的預期。不幸的是,如果輸入的命令會對系統造成損害,GNU Parallel 唯一能做的就是更快地對其造成損害!
GNU Parallel 示例#1:從網絡下載文件
對於這個任務,您將從網絡上的各種 URL 下載文件列表。例如,這些 URL 可能代表您想保存的網頁、圖像,甚至是來自 FTP 伺服器的文件列表。
在這個示例中,您將從 GNU parallel 的 FTP 伺服器下載一系列存檔套件(以及 SIG 檔案)。
1. 創建一個名為download_items.txt的文件,從官方下載站點中抓取一些下載鏈接,並將它們添加到文件中,以換行符分隔。
您可以使用 Python 的Beautiful Soup library從下載頁面中提取所有鏈接,從而節省一些時間。
2. 從download_items.txt文件中讀取所有 URL,並將它們傳遞給 Parallel,它將調用wget
並傳遞每個 URL。
不要忘記,在並行命令中,
{}
是輸入字符串的佔位符!
3. 也许你需要控制GNU Parallel同时使用的线程数。如果是这样,请在命令中添加--jobs
或-j
参数。--jobs
参数限制可以同时运行的线程数为你指定的数字。
例如,要限制Parallel一次下载五个URL,命令如下:
上述命令中的
--jobs
参数可以调整为下载任意数量的文件,只要你运行的计算机有足够多的CPU来处理它们。
4. 为了演示--jobs
参数的效果,现在调整任务数量并运行time
命令来测量每次运行的时间。
GNU Parallel示例 #2: 解压缩存档文件
现在你已经从前面的示例中下载了所有这些存档文件,现在你必须解压缩它们。
在与存档文件相同的目录下运行以下Parallel命令。注意使用了通配符(*
)。由于该目录中包含存档包和SIG文件,你必须告诉Parallel只处理.tar.bz2文件。
奖励!如果你在交互式使用GNU parallel(而不是在脚本中),添加--bar
标志可以让Parallel在任务运行时显示进度条。

--bar
flagGNU Parallel示例 #3: 删除文件
如果你按照示例一和示例二进行了操作,现在你的工作目录中应该有很多占用空间的文件夹。所以让我们并行地删除所有这些文件!
要使用Parallel刪除所有以parallel-開頭的資料夾,請列出所有資料夾,並將每個資料夾路徑通過管道傳遞給Parallel,在每個資料夾上執行rm -rf
,如下所示。
記得使用
--dryrun
標誌!
結論
現在您可以使用Bash自動化任務,並節省大量時間。您如何利用這段時間取決於您。節省時間是提早離開工作還是閱讀另一篇ATA博客文章,這是您一天中的時間。
現在想想您環境中的所有長時間運行的腳本。您可以用Parallel加速哪些?
Source:
https://adamtheautomator.com/how-to-speed-up-bash-scripts-with-multithreading-and-gnu-parallel/