machineB
작업 중이어서 파일을 복사하려고 합니다 .machineC
machineA
machineA
파일이 없으면 machineB
분명히 존재해야 하므로 machineC
먼저 파일을 복사해 보고 machineB
, 없으면 machineB
에서 동일한 파일을 복사해 보겠습니다 machineC
.
저는 GNU 병렬 라이브러리를 사용하여 파일을 병렬로 복사하고 있는데 잘 작동합니다. 현재 두 개의 파일을 병렬로 복사하고 있습니다.
현재 나는 GNU를 사용하여 폴더 PRIMARY_PARTITION
의 파일을 PRIMARY
병렬로 복사하고 있으며 일단 완료되면 동일한 GNU를 사용하여 폴더 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[@]}"
문제 설명:-
두 개의 스레드를 시작할 수 있는 방법이 있습니까? 하나의 스레드는 PRIMARY
위와 동일한 설정을 사용하여 폴더의 파일을 복사합니다. 즉, 두 파일을 병렬로 복사한다는 의미입니다. 두 번째 스레드는 SECONDARY
위와 동일한 설정을 사용하여 폴더의 파일을 복사합니다. 두 파일도 동시에 병렬로 복사해야 합니까?
이는 폴더가 완료된 후 폴더의 파일을 복사하는 것이 PRIMARY
아니라 폴더의 파일을 동시에 병렬로 복사해야 함을 의미합니다 .SECONDARY
PRIMARY
SECONDARY
현재는 PRIMARY
폴더 파일이 완성되면 나만 SECONDARY
폴더 안의 파일을 복사하려고 합니다.
즉, 두 개의 스레드를 시작하면 됩니다. 하나의 스레드가 이를 실행합니다.
# 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[@]}"
모든 파일이 성공적으로 복사되면 모든 파일이 복사되었습니다라는 메시지가 표시됩니다. Java에서는 두 개의 스레드를 시작하고 각 스레드가 특정 작업을 수행하는 방법을 알고 있지만 이것이 bash 쉘 스크립트에서 어떻게 작동하는지 잘 모르십니까?
PRIMARY
내 주요 작업은 SECONDARY
GNU 병렬을 사용하여 폴더 안팎으로 두 개의 파일을 동시에 복사하는 것입니다.
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를 실행하는 대신 하나의 명령으로 모든 파일을 복사하면 많은 시간과 노력을 절약하고 데이터가 올바르게 복사되도록 할 수 있습니다. 또한 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