NFS에 대해 물었습니다. 검사 noclobber
에는 두 개의 개별 NFS 작업 (파일이 존재하는지 확인하고 새 파일 작성)이 포함되고 두 개의 개별 NFS 클라이언트의 두 프로세스가 경쟁 조건에 빠질 수 있기 때문에 이러한 종류의 코드는 NFS에서 작동하지 않을 수 있습니다 ( 둘 다 B.part
아직 존재하지 않는지 확인한 다음 성공적으로 작성하여 서로 겹쳐 씁니다.)
작성하려는 파일 시스템이 noclobber
원자 와 같은 것을 지원하는지 여부에 대한 일반적인 검사는 실제로 수행하지 않습니다. 파일 시스템 유형을 NFS인지 여부를 확인할 수 있지만 휴리스틱 일 수 있으며 반드시 보장 할 필요는 없습니다. SMB / CIFS (Samba)와 같은 파일 시스템은 동일한 문제를 겪을 수 있습니다. 파일 시스템은 FUSE를 통해 노출되거나 올바르게 작동하지 않을 수 있지만 대부분 구현에 따라 다릅니다.
더 나은 방법은 B.part
다른 에이전트와의 협력을 통해 고유 한 파일 이름을 사용하여 단계 에서 충돌을 피하여 에 의존 할 필요가 없도록하는 것입니다 noclobber
. 예를 들어 파일 이름의 일부로 호스트 이름, PID 및 타임 스탬프 (+ 난수)를 포함 할 수 있습니다. 주어진 시간에 호스트의 특정 PID에서 단일 프로세스를 실행해야하므로, 독창성을 보장합니다.
따라서 다음 중 하나
test -f B && continue # skip already existing
unique=$(hostname).$$.$(date +%s).$RANDOM
cp A B.part."$unique"
# Maybe check for existance of B again, remove
# the temporary file and bail out in that case.
mv B.part."$unique" B
# mv (rename) should always succeed, overwrite a
# previously copied B if one exists.
또는:
test -f B && continue # skip already existing
unique=$(hostname).$$.$(date +%s).$RANDOM
cp A B.part."$unique"
if ln B.part."$unique" B ; then
echo "Success creating B"
else
echo "Failed creating B, already existed"
fi
# Both cases require cleanup.
rm B.part."$unique"
따라서 두 에이전트간에 경쟁 조건이있는 경우 둘 다 작업을 진행하지만 마지막 작업은 원자 적이므로 B는 A의 전체 사본으로 존재하거나 B는 존재하지 않습니다.
복사 후 mv
또는 ln
작업 전에 다시 확인하여 레이스의 크기를 줄일 수 있지만 여전히 작은 경합 상태가 있습니다. 그러나 경쟁 조건에 관계없이 두 프로세스가 모두 A (또는 유효한 파일에서 원본으로 사본)를 작성하려고하면 B의 내용은 일관성이 있어야합니다.
의 첫 번째 상황 mv
에서 레이스가 존재할 때 rename (2) 이 기존 파일을 원자 적으로 대체 하므로 마지막 프로세스가이기는 프로세스입니다 .
경우 newpath를가 이미 존재 액세스를 시도하는 다른 프로세스에있는 아무 소용이 없도록, 그것은 원자, 대체됩니다 newpath를가 누락 찾을 수가. [...]
경우 newpath를가 존재하지만 작업이 어떤 이유로 실패, rename()
보장의 인스턴스 떠날 하는 newpath을 장소에서.
따라서 당시 B를 소비하는 프로세스는이 프로세스 중에 다른 버전 (다른 inode)을 볼 수 있습니다. 작가가 모두 동일한 내용을 복사하려고 시도하고 독자가 단순히 파일의 내용을 소비하는 경우, 동일한 내용의 파일에 대해 다른 inode를 얻는다면 괜찮을 것입니다.
하드 링크를 사용하는 두 번째 접근 방식 이 더 좋아 보이지만 많은 동시 클라이언트의 NFS에서 빡빡한 루프로 하드 링크로 실험을하고 성공을 계산 한 것으로 기억합니다. 두 클라이언트가 하드 링크를 발급 한 경우 여전히 경쟁 조건이있는 것처럼 보입니다. 동일한 목적지에서 동시에 작업이 성공한 것 같습니다. (이 동작은 특정 NFS 서버 구현 인 YMMV와 관련이있을 수 있습니다.) 어쨌든 같은 종류의 경쟁 조건 일 수 있습니다.이 경우 동일한 파일에 대해 두 개의 개별 inode가 생길 수 있습니다. 이러한 경쟁 조건을 유발하기 위해 작가 간의 동시성 작가가 일관성 있고 (A를 B로 복사) 독자가 내용 만 소비한다면 충분할 수 있습니다.
마지막으로 잠금을 언급했습니다. 불행히도 잠금은 적어도 NFSv3에서 심각하게 부족합니다 (NFSv4에 대해서는 확실하지 않지만 좋지는 않을 것입니다.) 잠금을 고려하고 있다면 분산 잠금을 위해 다른 프로토콜을 살펴 봐야 할 것입니다. 실제 파일 사본이지만 교착 상태와 같은 문제가 발생하기 쉬우 며 복잡하고 피할 수 있으므로 피하는 것이 좋습니다.
NFS에서 원자 성의 주제에 대한 자세한 배경 정보를 보려면 Maildir 메일 박스 형식 을 읽으십시오.이 형식 은 잠금을 피하고 NFS에서도 안정적으로 작동합니다. 모든 곳에서 고유 한 파일 이름을 유지하여 그렇게합니다 (결국 최종 B도 얻지 못합니다).
아마도 좀 더 흥미로운 특정 케이스의 Maildir 형식 ++ 형식은 사서함 할당량에 대한 지원을 추가 할 Maildir 형식을 확장하고 원자 (즉 가깝게 B로 될 수 있도록) 나는 Maildir 형식 ++ 시도를 생각 사서함 내부에 고정 된 이름의 파일을 업데이트하여 그렇게 추가하는 것은 NFS에서는 실제로 안전하지 않지만 이와 비슷한 절차를 사용하는 재 계산 접근법이 있으며 원자 교체로 유효합니다.
잘만되면이 모든 포인터가 유용 할 것입니다!