답변:
파일 시스템 경계를 넘어 파일을 이동하지 않는 한 작업이 안전해야합니다. 이것은»moving«이 실제로 수행되는 메커니즘 때문입니다.
당신이 경우 mv동일한 파일 시스템에있는 파일은 파일이 실제로 접촉하지 않고, 단지 파일 시스템 항목이 변경됩니다.
$ mv foo bar
실제로 같은 것을한다
$ ln foo bar
$ rm foo
이렇게하면 이름이 지정된 파일 (실제로는 파일 시스템 항목이 가리키는 inode)에 대한 하드 링크 (두 번째 디렉토리 항목) 가 생성 되고 항목이 제거 됩니다. 를 제거 할 때 inode를 가리키는 두 번째 파일 시스템 항목이 있으므로 이전 항목을 제거해도 실제로 inode에 속하는 블록은 제거되지 않습니다.foobarfoofoofoofoo
열려있는 파일 핸들이 파일 시스템 항목이 아니라 파일의 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에 추가되었습니다.