使用並行將唯一的輸入文件處理為唯一的輸出文件
我有一個 shell 腳本問題,我得到一個充滿輸入文件的目錄(每個文件包含許多輸入行),我需要單獨處理它們,將它們的每個輸出重定向到一個唯一的文件(又名 file_1.input 需要在 file_1.output 中擷取,依此類推)。
預並行,我將遍歷目錄中的每個文件並執行我的命令,同時執行某種計時器/計數技術以不使處理器不堪重負(假設每個程序都有一個恆定的執行時間)。但是,我知道情況並非總是如此,因此使用類似“並行”的解決方案似乎是在不編寫自定義程式碼的情況下獲得 shell 腳本多執行緒的最佳方式。
雖然我已經想到了一些方法來並行處理這些文件中的每一個(並允許我有效地管理我的核心),但它們看起來都很老套。我有一個我認為非常簡單的案例,因此希望盡可能保持乾淨(並且並行範例中似乎沒有任何問題是我的問題。
任何幫助,將不勝感激!
輸入目錄範例:
> ls -l input_files/ total 13355 location1.txt location2.txt location3.txt location4.txt location5.txt
腳本:
> cat proces_script.sh #!/bin/sh customScript -c 33 -I -file [inputFile] -a -v 55 > [outputFile]
更新:在閱讀了下面 Ole 的回答後,我能夠為我自己的並行實現整理缺少的部分。雖然他的回答很好,但這是我的補充研究和筆記:
我沒有執行我的整個過程,而是想從一個概念證明命令開始,以在我的環境中證明他的解決方案。請參閱我的兩個不同的實現(和註釋):
find /home/me/input_files -type f -name *.txt | parallel cat /home/me/input_files/{} '>' /home/me/output_files/{.}.out
使用 find(不是 ls,可能會導致問題)在我的輸入文件目錄中查找所有適用的文件,然後將它們的內容重定向到單獨的目錄和文件。我上面的問題是閱讀和重定向(實際腳本很簡單),所以用 cat 替換腳本是一個很好的概念證明。
parallel cat '>' /home/me/output_files/{.}.out ::: /home/me/input_files/*
第二個解決方案使用並行的輸入變數範例來讀取文件,但是對於新手來說,這更加令人困惑。對我來說,使用 find a 和 pipe 很好地滿足了我的需求。
GNU Parallel 專為此類任務而設計:
parallel customScript -c 33 -I -file {} -a -v 55 '>' {.}.output ::: *.input
要麼:
ls | parallel customScript -c 33 -I -file {} -a -v 55 '>' {.}.output
它將每個 CPU 核心執行一個作業。
您可以通過以下方式安裝 GNU Parallel:
wget https://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel chmod 755 parallel cp parallel sem
觀看 GNU Parallel 的介紹影片以了解更多資訊: https ://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
執行此操作的標準方法是設置一個隊列並生成任意數量的工作人員,這些工作人員知道如何從隊列中提取某些內容並進行處理。您可以使用 fifo(又名命名管道)在這些程序之間進行通信。
下面是一個簡單的例子來展示這個概念。
一個簡單的隊列腳本:
#!/bin/sh mkfifo /tmp/location-queue for i in inputfiles/*; do echo $i > /tmp/location-queue done rm /tmp/location-queue
還有一個工人:
#!/bin/sh while read file < /tmp/location-queue; do process_file "$file" done
process_file
可以在你的工作人員的某個地方定義,它可以做你需要做的任何事情。一旦你有了這兩個部分,你就可以有一個簡單的監視器來啟動隊列程序和任意數量的工作程序。
監控腳本:
#!/bin/sh queue.sh & num_workers="$1" i=0 while [ $i < $num_workers ]; do worker.sh & echo $! >> /tmp/worker.pids i=$((i+1)) done monitor_workers
你有它。如果您確實這樣做,最好在監視器中設置 fifo,並將路徑傳遞給隊列和工作人員,這樣它們就不會耦合,也不會粘在 fifo 的特定位置。我在答案中專門設置了這種方式,因此很清楚您在閱讀時使用的是什麼。