machineB
で以下のシェルスクリプトを実行しているため、machineC
およびmachineA
からmachineA
にファイルをコピーしようとしています。
ファイルがmachineB
にない場合は、確かにmachineC
にあるはずなので、最初にmachineB
からファイルをコピーしてみます。machineB
にない場合は、machineC
から同じファイルをコピーしてみます。
GNU並列ライブラリを使用してファイルを並列にコピーしていますが、正常に動作しています。現在、2つのファイルを並行してコピーしています。
現在、GNU並列を使用してPRIMARY
フォルダー内の_PRIMARY_PARTITION
_ファイルをコピーしています。これが完了すると、同じGNU並列を使用してSECONDARY
フォルダー内の_SECONDARY_PARTITION
_ファイルをコピーします。現在はwrt 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
フォルダー内のファイルをコピーする2番目のスレッドは、同時に2つのファイルを並行してコピーする必要がありますか?
つまり、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シェルスクリプトでこれがどのように機能するかわかりませんか?
私の主なタスクは、GNU並列を使用して、2つのファイルをPRIMARY
フォルダーとSECONDARY
フォルダーに同時にコピーすることですか?
これはbashシェルスクリプトで実行できますか?
明白です:
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に制限します。
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
コードブロックを関数でラップし、その関数をバックグラウンドジョブとして実行することで、同じ効果を得ることができます。
または、中括弧の代わりに括弧でコードブロックをラップすることもできます。括弧内のステートメントは、明示的に(常に)別のプロセスで実行されます。通常、中括弧で囲まれたステートメントはグループ化されますが、分岐せずに実行されます。 &
サフィックスを使用してバックグラウンドでコードを実行すると、そのコードは強制的に別のプロセスで実行されます。
これには、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