rm, nullcopy, truncate의 차이
📘 OEA
로그 파일을 지울 때 왜 어떤 방식은 로그가 계속 쌓이고, 어떤 방식은 안 보일까
운영 중 로그 파일을 비워야 할 때 흔히 rm을 쓰곤 합니다.
그런데 nohup ... > app.log 2>&1 & 형태로 실행한 프로세스에서는 rm으로 로그 파일을 지우면, 그 뒤부터 로그가 안 쌓이는 것처럼 보이는 경우가 있습니다. 반면 nullcopy나 truncate로 파일을 비우면 이후 로그는 계속 정상적으로 쌓입니다.
이 차이는 단순히 “파일을 지웠다”와 “파일 내용을 비웠다”의 차이에서 나옵니다.
rm은 파일 이름을 없애는 동작입니다
rm app.log는 파일 내용을 비우는 것이 아니라, 파일 시스템에서 app.log라는 이름을 제거합니다.
하지만 이미 실행 중인 프로세스는 시작 시점에 app.log를 열어 둔 상태입니다.
즉 프로세스는 파일 이름으로 쓰는 것이 아니라, 이미 열어 둔 파일 디스크립터를 통해 계속 로그를 기록합니다.
이 상태에서 rm을 하면:
- 디렉토리에서는
app.log가 사라집니다 - 하지만 프로세스는 예전에 열어 둔 파일에 계속 씁니다
- 사용자는 파일이 안 보이니 “로그가 안 쌓인다”고 느끼게 됩니다
정확히 말하면 로그가 안 쌓이는 것이 아니라, 삭제된 파일에 계속 기록되고 있는 상태입니다.
nullcopy와 truncate는 파일을 유지한 채 내용만 비웁니다
반면 nullcopy나 truncate는 파일 자체를 삭제하지 않습니다.
기존 파일을 그대로 둔 채 내용만 0바이트로 만드는 방식입니다.
대표적으로 아래와 같은 방식이 여기에 해당합니다.
cat /dev/null > app.log
truncate-s0 app.log
: > app.log
이 방식은:
- 파일 이름 유지
- inode 유지
- 프로세스가 잡고 있는 파일 디스크립터 유지
- 파일 내용만 초기화
라는 특징이 있습니다.
그래서 프로세스는 같은 파일에 계속 로그를 쓸 수 있고, 사용자는 이후 로그가 정상적으로 다시 쌓이는 것을 확인할 수 있습니다.
왜 이런 차이가 생길까
핵심은 프로세스가 로그를 파일 경로명으로 쓰는 것이 아니라, 실행 시점에 이미 열어 둔 파일 핸들로 쓴다는 점입니다.
즉:
rm은 파일 이름을 없앰truncate계열은 파일 이름과 연결 상태를 유지한 채 내용만 비움
그래서 nohup 리다이렉션 기반 로그에서는 두 방식의 결과가 완전히 다르게 보입니다.
정리
운영 중 로그 파일을 비울 때는 다음처럼 이해하면 됩니다.
rm→ 파일을 삭제 → 실행 중인 프로세스는 기존 열린 파일에 계속 기록 → 새 로그가 안 보이는 것처럼 보일 수 있음nullcopy,truncate→ 파일은 유지하고 내용만 비움 → 실행 중인 프로세스가 같은 파일에 계속 기록 가능 → 이후 로그가 정상적으로 쌓임
결론
nohup ... > log 2>&1 & 형태로 실행한 프로세스의 로그를 비울 때는 rm보다 truncate 계열이 안전합니다.
짧게 정리하면 이렇습니다.
rm은 파일을 지우는 것이고, nullcopy와 truncate는 파일을 살려 둔 채 내용만 비우는 것이다. 실행 중인 프로세스의 로그 파일이라면 이 차이가 그대로 운영 결과 차이로 이어진다.