sed를 사용하여 사용자 입력에 따라 파일을 수정하는 쉘/파이썬 스크립트가 있는 경우 두 명의 사용자가 동시에 또는 거의 동시에 동일한 스크립트를 실행합니다. 또한 "sed" 스레드는 안전한가요? 아니면 첫 번째 스레드에 의해 열린 file_descriptor가 어쨌든 파일을 잠그는 데 사용되기 때문에 문제가 되지 않을 수도 있습니까? 감사해요
답변1
끔찍한 용어에 대해서는 논쟁하지 않겠습니다. 하지만 그렇습니다. GNU sed 및 해당 ("in-place") 플래그는 파일이 실제로 수정되지 않기 -i
때문에 추가 잠금 없이 동시에 여러 프로세스에서 안전하게 사용할 수 있습니다 . sed
그러나 출력을 임시 파일로 리디렉션하고 모든 것이 잘되면 rename(2)
임시 파일을 원본 파일로 이동(이동)하여 rename(2)
원자성이 보장됩니다.
$ strace sed -i s/o/e/g foo.txt
open("foo.txt", O_RDONLY) = 3
...
open("./sedDe80VL", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
...
read(3, "foo\n", 4096) = 4
...
write(4, "fee\n", 4) = 4
read(3, "", 4096) = 0
...
close(3) = 0
close(4) = 0
rename("./sedDe80VL", "foo.txt") = 0
항상 foo.txt
전체 원본 파일이나 전체 처리된 파일이 참조되며, 그 사이에는 어떤 것도 참조되지 않습니다.
노트:
이는 다른 프로세스가 편집을 완료할 때까지 기다리지 않고 여러 프로세스가 파일 편집을 시작하는 상황을 처리할 수 없습니다. 이 경우 마지막에 "승리"한 프로세스만 완료됩니다(즉, 다른 프로세스에서 수행한 변경 사항이 삭제됩니다). 이는 데이터 무결성 문제가 아니며 프로세스 간의 더 높은 수준의 조정 없이는 처리할 수 없습니다. 파일을 맹목적으로 잠그면 교착 상태가 발생합니다.
현재 GNU sed는 표준 파일 권한을 새 inode에 복사하지만 ACL 및 확장 속성은 복사하지 않습니다. sed -i
이러한 파일에 사용 하면 모든 추가 메타데이터가 손실됩니다. IMHO 이것은 버그나 제한이라기보다는 기능에 가깝습니다.
perl -i
작동 방식은 sed -i
이전 버전 과 매우 다릅니다 5.28
. 먼저 파일의 임시 복사본을 만들고 원본 파일로 자른 다음 출력을 해당 파일로 리디렉션합니다. 이렇게 하면 원래 inode 번호와 추가 메타데이터가 유지되지만 perl -i
프로세스가 중단 perl -i
되거나 여러 프로세스가 동시에 파일을 편집하는 경우 파일 내용이 완전히 삭제됩니다 . 보다논의하다, 원래의범죄(향후 개선됨) 및 변경 로그perl5280delta.
답변2
여러 병렬 작업에 대해 동일한 파일에 sed -i를 사용하는 것은 권장되지 않지만, 필요한 경우...
작동하게 만드는 패턴은 다음과 같습니다. 신호.
기능적 스레드 인식 방식으로 동일한 파일에서 sed -i에 대한 비동기 호출을 허용하려면 다음을 사용하십시오.컨설팅 락.
flock theSharedFile sed -i s/"userInput1"/"$userInput2"/g theSharedFile
Flock은 SharedFile에 권고 잠금을 생성하고 잠금이 해제되면(SharedFile에서 실행 중인 다른 클러스터가 없을 때) 나머지 매개변수를 사용하여 sed 명령이 실행됩니다.
두 명의 다른 사용자가 동시에 실행하면 두 번째 사용자는 이전 사용자가 완료될 때까지 기다립니다. 이와 같이 완전히 기능적이고 스레드로부터 안전한 방법이 됩니다. 모든 "사용자" 변경 사항은 삭제되거나 덮어쓰여지지 않습니다.
권고 잠금이므로 클러스터에만 적합하며 어떤 종류의 교착 상태도 발생하지 않습니다. 파일을 읽는 사람은 잠기지 않습니다. 파일이 큰 경우 잠금을 기다리는 프로세스에 상당한 시간이 걸릴 수 있습니다.
현재 잠금을 나열할 수 있습니다.lslocks
이것이 누군가에게 도움이 되기를 바랍니다. 시간 내 주셔서 감사합니다.