machineB
作業中でファイルをコピーしようとしています。machineC
machineA
machineA
ファイルがない場合はmachineB
明らかに存在する必要があるので、machineC
まずファイルをコピーしてみてください。そうでない場合は同じファイルをコピーしてみましょう。machineB
machineB
machineC
私はGNUパラレルライブラリを使ってファイルをパラレルにコピーしていますが、うまくいきます。現在、2つのファイルを並列にコピーしています。
現在、私はGNUを使用してフォルダ内のファイルを並列にコピーしています。完了したら、同じGNUを使用してフォルダ内のファイルを並列にコピーしPRIMARY_PARTITION
ます。これまでは連続的でフォルダPRIMARY
SECONDARY_PARTITION
SECONDARY
PRIMARY
SECONDARY
以下は私のシェルスクリプトです。すべてがうまくいきます。
#!/bin/bash
export PRIMARY=/test01/primary
export SECONDARY=/test02/secondary
readonly FILERS_LOCATION=(machineB machineC)
export FILERS_LOCATION_1=${FILERS_LOCATION[0]}
export FILERS_LOCATION_2=${FILERS_LOCATION[1]}
PRIMARY_PARTITION=(550 274 2 546 278) # this will have more file numbers
SECONDARY_PARTITION=(1643 1103 1372 1096 1369) # this will have more file numbers
export dir3=/testing/snapshot/20140103
# delete primary files first and then copy
find "$PRIMARY" -mindepth 1 -delete
do_CopyInPrimary() {
el=$1
scp david@$FILERS_LOCATION_1:$dir3/new_weekly_2014_"$el"_200003_5.data $PRIMARY/. || scp david@$FILERS_LOCATION_2:$dir3/new_weekly_2014_"$el"_200003_5.data $PRIMARY/.
}
export -f do_CopyInPrimary
parallel -j 2 do_CopyInPrimary ::: "${PRIMARY_PARTITION[@]}"
# delete secondary files first and then copy
find "$SECONDARY" -mindepth 1 -delete
do_CopyInSecondary() {
el=$1
scp david@$FILERS_LOCATION_1:$dir3/new_weekly_2014_"$el"_200003_5.data $SECONDARY/. || scp david@$FILERS_LOCATION_2:$dir3/new_weekly_2014_"$el"_200003_5.data $SECONDARY/.
}
export -f do_CopyInSecondary
parallel -j 2 do_CopyInSecondary ::: "${SECONDARY_PARTITION[@]}"
問題の説明:-
2つのスレッドを起動する方法はありますか? 1つのスレッドはPRIMARY
上記と同じ設定を使用してフォルダ内のファイルをコピーします。つまり、両方のファイルを並列にコピーするという意味です。 2番目のスレッドは、SECONDARY
上記と同じ設定を使用してフォルダ内のファイルをコピーします。両方のファイルも同時に並列にコピーする必要がありますか?
これは、フォルダが完了した後にフォルダ内のファイルをコピーするのではなく、フォルダPRIMARY
内のファイルを同時に並列にコピーする必要があることを意味します。SECONDARY
PRIMARY
SECONDARY
現時点では、PRIMARY
フォルダファイルが完成したら、私だけがSECONDARY
フォルダ内のファイルをコピーしようとしています。
つまり、2つのスレッドを起動するだけです。 1つのスレッドがこれを実行します。
# delete primary files first and then copy
find "$PRIMARY" -mindepth 1 -delete
do_CopyInPrimary() {
el=$1
scp david@$FILERS_LOCATION_1:$dir3/new_weekly_2014_"$el"_200003_5.data $PRIMARY/. || scp david@$FILERS_LOCATION_2:$dir3/new_weekly_2014_"$el"_200003_5.data $PRIMARY/.
}
export -f do_CopyInPrimary
parallel -j 2 do_CopyInPrimary ::: "${PRIMARY_PARTITION[@]}"
2番目のスレッドはこれを実行します -
# delete secondary files first and then copy
find "$SECONDARY" -mindepth 1 -delete
do_CopyInSecondary() {
el=$1
scp david@$FILERS_LOCATION_1:$dir3/new_weekly_2014_"$el"_200003_5.data $SECONDARY/. || scp david@$FILERS_LOCATION_2:$dir3/new_weekly_2014_"$el"_200003_5.data $SECONDARY/.
}
export -f do_CopyInSecondary
parallel -j 2 do_CopyInSecondary ::: "${SECONDARY_PARTITION[@]}"
すべてのファイルが正常にコピーされると、すべてのファイルがコピーされましたというメッセージが表示されます。 Javaでは2つのスレッドを起動し、各スレッドが特定のタスクを実行する方法を知っていますが、これがbashシェルスクリプトでどのように機能するのかわかりませんか?
PRIMARY
私の主な作業は、SECONDARY
GNUパラレルを使用して2つのファイルをフォルダの内外に同時にコピーすることです。
bashシェルスクリプトでこれを実行できますか?
答え1
Bashはスレッドをサポートしていませんが、バックグラウンドマルチプロセッシングをサポートしています。つまり、プロセスは独自の環境、作業ディレクトリなどの新しいプロセススペースに複製され、すべての通信は通常のIPCチャネルを介して行われる必要があります。しかし、それ以外はスレッドと非常に似ているようです。
コードブロックを「コンテキスト化」することでこれを行うことができます。このように:
#!/bin/bash
{
echo "Foo"
sleep 1
echo "Foo: done"
}&
echo "Bar"
sleep 1
echo "Bar: done"
出力
Bar
Foo
**[1 second delay]**
Bar: done
Foo: done
関数にコードブロックをラップし、その関数をバックグラウンドジョブとして実行すると、同じ効果が得られます。
あるいは、中括弧の代わりに括弧でコードブロックを囲むこともできます。中括弧で囲まれたステートメントは、明示的に(常に)別々のプロセスで実行されます。通常、中括弧で囲まれたステートメントはグループ化されますが、実行時には分岐しません。サフィックスを使用してバックグラウンドでコードを実行すると、&
コードは別のプロセスで実行されます。
答え2
明らかなものは次のとおりです。
parallel -j 2 do_CopyInPrimary ::: "${PRIMARY_PARTITION[@]}" &
parallel -j 2 do_CopyInSecondary ::: "${SECONDARY_PARTITION[@]}" &
wait
ただし、この方法では、セカンダリサーバーはプライマリサーバーが完了するのを待たず、プライマリサーバーが成功したことを確認しません。 $PRIMARY_PARTITION[1] が $SECONDARY_PARTITION[1] に対応すると仮定します。したがって、$PRIMARY_PARTITION[1] からファイルを読み取れない場合は、$SECONDARY_PARTITION[1] からファイルを読み込みます。これは $PRIMARY_PARTITION と $SECONDARY_PARTITION も意味します。同じ数の要素があります)。その後、$PRIMARY_PARTITION[1]から$SECONDARY_PARTITION[1]の動作を規制できます。
do_Copy() {
PRIMARY_PARTITION=(550 274 2 546 278) # this will have more file numbers
SECONDARY_PARTITION=(1643 1103 1372 1096 1369) # this will have more file numbers
pel=${PRIMARY_PARTITION[$1]}
sel=${SECONDARY_PARTITION[$1]}
do_CopyInPrimary $pel ||
do_CopyInSecondary $sel ||
echo Could not copy neither $pel nor $sel
}
export -f do_Copy
# Number of elements in PRIMARY_PARTITION == SECONDARY_PARTITION
seq ${#PRIMARY_PARTITION[@]} | parallel -j 2 do_Copy
これにより依存関係が正確になりますが、一度に合計2つだけコピーされます。-j4
同時に4つの予備選挙がある危険がありますので、これにも注意する必要があります。
do_Copy() {
PRIMARY_PARTITION=(550 274 2 546 278) # this will have more file numbers
SECONDARY_PARTITION=(1643 1103 1372 1096 1369) # this will have more file numbers
pel=${PRIMARY_PARTITION[$1]}
sel=${SECONDARY_PARTITION[$1]}
sem -j2 --fg --id primary do_CopyInPrimary $pel ||
sem -j2 --fg --id secondary do_CopyInSecondary $sel ||
echo Could not copy neither $pel nor $sel
}
export -f do_Copy
# Number of elements in PRIMARY_PARTITION == SECONDARY_PARTITION
seq ${#PRIMARY_PARTITION[@]} | parallel -j 4 do_Copy
sem
基本数量を2個、補助数量を2個に制限します。
答え3
これを行うには、scpの代わりにrsyncを使用することをお勧めします。各ファイルに対して scp を実行するのではなく、1 つのコマンドですべてのファイルをコピーすると、時間と労力を大幅に節約でき、データが正しくコピーされるようになります。また、machineCから既存のファイルのコピーをスキップします。このような:
#!/bin/bash
files="one two three"
machines="machineB machineC"
for machine in machines
do
ssh $machine -c "cd source_directory || exit 1; rsync -avPz --ignore-existing $files machineA:/receive_directory/"
done