답변:
파일 시스템 경계를 넘어 파일을 이동하지 않는 한 작업이 안전해야합니다. 이것은»moving«이 실제로 수행되는 메커니즘 때문입니다.
당신이 경우 mv
동일한 파일 시스템에있는 파일은 파일이 실제로 접촉하지 않고, 단지 파일 시스템 항목이 변경됩니다.
$ mv foo bar
실제로 같은 것을한다
$ ln foo bar
$ rm foo
이렇게하면 이름이 지정된 파일 (실제로는 파일 시스템 항목이 가리키는 inode)에 대한 하드 링크 (두 번째 디렉토리 항목) 가 생성 되고 항목이 제거 됩니다. 를 제거 할 때 inode를 가리키는 두 번째 파일 시스템 항목이 있으므로 이전 항목을 제거해도 실제로 inode에 속하는 블록은 제거되지 않습니다.foo
bar
foo
foo
foo
foo
열려있는 파일 핸들이 파일 시스템 항목이 아니라 파일의 inode를 가리 키므로 프로그램은 파일에 행복하게 추가됩니다.
참고 : 프로그램이 쓰기 사이에 파일을 닫았다가 다시 열면 이전 파일 시스템 항목으로 작성된 새 파일이 생깁니다!
파일 시스템 간 이동 :
파일 시스템 경계를 넘어 파일을 이동하면 문제가 발생합니다. 이 경우 mv
실제로 파일이 일관성을 유지하도록 보장 할 수 없었습니다.
또는
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
각하
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
응용 프로그램을 쓰는 동안 복사가 파일 끝에 도달하는지 여부에 따라 새 파일에 절반의 줄만있을 수 있습니다.
또한 응용 프로그램이 이전 파일을 닫았다가 다시 열지 않으면 삭제 된 것처럼 보일지라도 이전 파일에 계속 기록합니다. 커널은 열려있는 파일을 알고 파일 시스템 항목을 삭제하더라도 파일 시스템 항목을 삭제합니다. 응용 프로그램이 열린 파일 핸들을 닫을 때까지 이전 파일의 inode 및 관련 블록을 삭제하지 않습니다.
file-system borders
입니까?
node.js를 사용하고 있다고 말했기 때문에 파일 이름을 바꾸기 위해 fs.rename()
(또는 fs.renameSync()
)를 사용한다고 가정 합니다. 이 node.js 메소드는 rename (2) 시스템 호출 을 사용하도록 문서화되어 있습니다.이 호출은 어떤 방식 으로든 파일 자체를 건드리지 않고 파일 시스템에 나열된 이름 만 변경합니다.
" 이름 바꾸기는 () 필요한 경우 디렉토리 사이를 이동, 파일 이름을 변경합니다. 기타 파일에 하드 링크 된 파일을 (사용하여 생성으로 링크 (2) ) 영향을받지 않습니다. 오픈 파일 기술자 oldpath는이 또한 영향을받지 않습니다."
특히, 위에서 인용 한 마지막 문장에 주목하십시오. 즉, 열려있는 파일 디스크립터 (예 : 프로그램이 파일에 쓰는 데 사용)는 파일 이름을 바꾼 후에도 계속 해당 파일을 가리 킵니다. 따라서 파일을 쓰는 동안 파일 이름이 바뀌더라도 데이터 손실이나 손상이 없습니다.
Andreas Weise가 그의 답변 에서 언급 한 것처럼 rename (2) 시스템 호출 (및 fs.rename()
node.js)은 파일 시스템 경계에서 작동하지 않습니다. 따라서이 방법으로 파일을 다른 파일 시스템으로 이동하려고하면 실패합니다.
Unix mv
명령은 오류를 감지하고 대신 내용을 새 파일로 복사하고 원본을 삭제하여 파일을 이동하여이 제한을 숨기려고합니다. 불행하게도, 이런 식으로 파일을 이동하는 것은 수행 이 기록되는 동안 파일을 이동하면 위험 데이터 손실을. 따라서 동시에 쓸 수있는 파일의 이름을 안전하게 바꾸려면 사용 하지 않아야 합니다 mv
(또는 적어도 새 경로와 이전 경로가 동일한 파일 시스템에 있는지 확인해야합니다).
rename()
시스템 호출 이 없었습니다 . 따라서 원래 버전은mv
실제로link()
하드 링크를 생성unlink()
하고 원래 이름을 제거 하기 위해 호출 했습니다 .rename()
커널에서 이것을 원자 적으로 구현하기 위해 FreeBSD에 추가되었습니다.