Linux

如何在 bash shell 腳本中一次複製三個文件而不是一個文件?

  • April 22, 2014

我正在執行我的 shell 腳本,在該腳本上將machineA文件複製machineB到.machineC``machineA

如果該文件不在 中machineB,那麼它肯定應該在其中machineC。所以我會先嘗試複製文件machineB,如果它不在那裡,machineB那麼我會去machineC複制相同的文件。

在這個文件夾machineB裡面machineC會有一個像這樣的YYYYMMDD文件夾 -

/data/pe_t1_snapshot

因此,無論日期是上述文件夾中這種格式的最新日期YYYYMMDD- 我都會選擇該文件夾作為我需要開始復製文件的完整路徑 -

20140317所以假設如果這是裡面的最新日期文件夾,/data/pe_t1_snapshot那麼這將是我的完整路徑 -

/data/pe_t1_snapshot/20140317

從我需要開始將文件複製到machineBmachineC. 我需要從和復製400文件,每個文件大小都是.machineA``machineB``machineC``2.5 GB

早些時候,我試圖一個一個地複製文件,machineA這真的很慢。有什麼辦法,我可以machineA在 bash shell 腳本中使用執行緒一次複製“三個”文件?

machineA下面是我的 shell 腳本,它從machineB和中一一複製文件machineC

#!/usr/bin/env bash

readonly PRIMARY=/export/home/david/dist/primary
readonly FILERS_LOCATION=(machineB machineC)
readonly MEMORY_MAPPED_LOCATION=/data/pe_t1_snapshot

PRIMARY_PARTITION=(0 548 272 4 544 276 8 556 280 12 552 284 16 256 564 20 260 560 24 264 572) # this will have more file numbers around 200

dir1=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[0]} ls -dt1 "$MEMORY_MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[1]} ls -dt1 "$MEMORY_MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)

## Build your list of filenames before the loop. 
for n in "${PRIMARY_PARTITION[@]}"
do
   primary_files="$primary_files :$dir1"/t1_weekly_1680_"$n"_200003_5.data
done

if [ "$dir1" = "$dir2" ]
then
   find "$PRIMARY" -mindepth 1 -delete
   rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ 2>/dev/null
   rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ 2>/dev/null
fi  

所以我在想而不是一次複製一個文件,為什麼不一次複製“三個”文件,一旦這三個文件完成,我將移動到列表中的另外三個文件同時複製?

我嘗試打開三個 putty 實例,並同時從這三個實例中複製一個文件。所有三個文件都在大約 50 秒內被複製,所以這對我來說很快。由於這個原因,我試圖一次複製三個文件而不是一次複製一個文件。

這可能嗎?如果是,那麼任何人都可以提供一個例子嗎?我只是想試一試,看看效果如何。

@terdon 幫助我完成了上述解決方案,但我想嘗試一次複製三個文件以查看它的行為。

更新:-

下面是上述 shell 腳本的簡化版本。當machineBmachineC在. _ 它將嘗試複製存在於.machineA``machineA``PRIMARY_PARTITION

#!/usr/bin/env bash

readonly PRIMARY=/export/home/david/dist/primary
readonly FILERS_LOCATION=(machineB machineC)
readonly MEMORY_MAPPED_LOCATION=/data/pe_t1_snapshot

PRIMARY_PARTITION=(0 548 272 4 544 276 8 556 280 12 552 284 16 256 564 20 260 560 24 264 572) # this will have more file numbers around 200

dir1=/data/pe_t1_snapshot/20140414
dir2=/data/pe_t1_snapshot/20140414

## Build your list of filenames before the loop. 
for n in "${PRIMARY_PARTITION[@]}"
do
   primary_files="$primary_files :$dir1"/t1_weekly_1680_"$n"_200003_5.data
done

if [ "$dir1" = "$dir2" ]
then
   # delete the files first and then copy it.
   find "$PRIMARY" -mindepth 1 -delete
   rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/
   rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/
fi

並行執行多個副本很少有用:無論限制因素是網路頻寬還是磁碟頻寬,您最終都會得到 N 個並行流,每個流的速度是 1/N 倍。

另一方面,當您從多個源(此處為 B 和 C)複製或複製到多個源(此處為 B 和 C)時,如果瓶頸在 B 和 C 一側(而不是在共同的一面)。因此,您可以嘗試並行執行副本:

rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ &
rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ &
wait

請注意,兩個 rsync 命令的輸出將混合在一起;您可能希望將其發送到單獨的文件中。

log_base=$(date +%Y%m%d-%H%M%S-$$)
rsync -avz david@${FILERS_LOCATION[0]}"${primary_files}" $PRIMARY/ >$log_base-B.log &
rsync -avz david@${FILERS_LOCATION[1]}"${primary_files}" $PRIMARY/ >$log_base-C.log &
wait

您在腳本中使用多個 SSH 連接到同一目標。建立 SSH 連接有不可避免的延遲。您可以通過保持連接打開並重複使用它來節省一點時間,這要歸功於主連接

引用自:https://unix.stackexchange.com/questions/125755