추가중인 파일을 이동해도 안전합니까?


28

fs.appendFile에 줄을 추가 하는 데 사용하는 node.js 프로세스가 있습니다 file.log. 라인 당 약 40 문자 만 전체 라인은 예를 들어, 호출처럼, 추가됩니다 fs.appendFile("start-end")없는이 같은 통화 fs.appendFile("start-")fs.appendFile("end"). 이 파일을 이동하면 file2.log줄이 손실되거나 부분적으로 복사되지 않을 수 있습니까?

답변:


36

파일 시스템 경계를 넘어 파일을 이동하지 않는 한 작업이 안전해야합니다. 이것은»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 및 관련 블록을 삭제하지 않습니다.


3
참고로, 초기 버전의 Unix에는 rename()시스템 호출 이 없었습니다 . 따라서 원래 버전은 mv실제로 link()하드 링크를 생성 unlink()하고 원래 이름을 제거 하기 위해 호출 했습니다 . rename()커널에서 이것을 원자 적으로 구현하기 위해 FreeBSD에 추가되었습니다.
Barmar

미안하지만 무엇 file-system borders입니까?
laike9m

1
@ laike9m-파일 시스템 경계는 간단한 파일 시스템이 디스크 드라이브와 같은 하나의 메모리 장치에서 하나의 파티션에 있어야한다는 사실을 나타냅니다. 파일 시스템 내에서 파일 이름을 바꾸면 디렉토리 항목의 이름 만 변경됩니다. 대부분의 Linux 파일 시스템과 마찬가지로 여전히 inode를 기반으로 파일 시스템에있는 경우 동일한 inode를 갖습니다. 그러나 파일을 다른 파일 시스템으로 이동하면 실제 데이터를 이동해야하며 파일은 새 파일 시스템에서 새 inode를 가져옵니다. 파일이 발생했을 때 진행중인 파일 작업이 중단됩니다.
Joe

9

node.js를 사용하고 있다고 말했기 때문에 파일 이름을 바꾸기 위해 fs.rename()(또는 fs.renameSync())를 사용한다고 가정 합니다. 이 node.js 메소드는 rename (2) 시스템 호출 을 사용하도록 문서화되어 있습니다.이 호출은 어떤 방식 으로든 파일 자체를 건드리지 않고 파일 시스템에 나열된 이름 만 변경합니다.

" 이름 바꾸기는 () 필요한 경우 디렉토리 사이를 이동, 파일 이름을 변경합니다. 기타 파일에 하드 링크 된 파일을 (사용하여 생성으로 링크 (2) ) 영향을받지 않습니다. 오픈 파일 기술자 oldpath는이 또한 영향을받지 않습니다."

특히, 위에서 인용 한 마지막 문장에 주목하십시오. 즉, 열려있는 파일 디스크립터 (예 : 프로그램이 파일에 쓰는 데 사용)는 파일 이름을 바꾼 후에도 계속 해당 파일을 가리 킵니다. 따라서 파일을 쓰는 동안 파일 이름이 바뀌더라도 데이터 손실이나 손상이 없습니다.


Andreas Weise가 그의 답변 에서 언급 한 것처럼 rename (2) 시스템 호출 (및 fs.rename()node.js)은 파일 시스템 경계에서 작동하지 않습니다. 따라서이 방법으로 파일을 다른 파일 시스템으로 이동하려고하면 실패합니다.

Unix mv명령은 오류를 감지하고 대신 내용을 새 파일로 복사하고 원본을 삭제하여 파일을 이동하여이 제한을 숨기려고합니다. 불행하게도, 이런 식으로 파일을 이동하는 것은 수행 이 기록되는 동안 파일을 이동하면 위험 데이터 손실을. 따라서 동시에 쓸 수있는 파일의 이름을 안전하게 바꾸려면 사용 하지 않아야 합니다 mv(또는 적어도 새 경로와 이전 경로가 동일한 파일 시스템에 있는지 확인해야합니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.