df와 du의 용량차이

권순선의 이미지

아래 화면에서 /var 에 해당하는 부분을 잘 보세요...

foo:/var# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              11G  8.1G  1.9G  81% /
/dev/vol/var           18G   16G  2.7G  85% /var
/dev/vol/home         4.9G  1.8G  3.1G  36% /home
/dev/vol/tmp          500M   61M  439M  13% /tmp
/dev/extra/data        70G  9.5G   60G  14% /data

foo:/var# du . -sh
5.4G    .
foo:/var#

df로 봤을 때는 총 크기 18G에서 16G가 사용되고 있다고 나오는데 막상 /var 에서 du로 확인하면 5.4G밖에 안됩니다. 왜 이런 현상이 일어나는지 알수가 없네요.

커널 2.4.24에 lvm 사용하고 있고, 파일시스템은 reiserfs 사용중입니다. lvm 메일링 리스트에 메일을 보내 보았는데 그쪽에서도 답장이 없군요. 혹시 이런 경우를 겪으신 분 있나요?

gbkwon의 이미지

권순선 wrote:
아래 화면에서 /var 에 해당하는 부분을 잘 보세요...

foo:/var# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              11G  8.1G  1.9G  81% /
/dev/vol/var           18G   16G  2.7G  85% /var
/dev/vol/home         4.9G  1.8G  3.1G  36% /home
/dev/vol/tmp          500M   61M  439M  13% /tmp
/dev/extra/data        70G  9.5G   60G  14% /data

foo:/var# du . -sh
5.4G    .
foo:/var#

df로 봤을 때는 총 크기 18G에서 16G가 사용되고 있다고 나오는데 막상 /var 에서 du로 확인하면 5.4G밖에 안됩니다. 왜 이런 현상이 일어나는지 알수가 없네요.

커널 2.4.24에 lvm 사용하고 있고, 파일시스템은 reiserfs 사용중입니다. lvm 메일링 리스트에 메일을 보내 보았는데 그쪽에서도 답장이 없군요. 혹시 이런 경우를 겪으신 분 있나요?

아파치나 MySQL 등의 로그 때문인것 같습니다 . 실제 로그 파일은 크기가 얼마 되지 않는데 어떠한 이유로 파일에 기록 하지 못하고 가지고 있는(?) 일이 있습니다..

저도 몇번이나 이런 경우를 겪었는데 아마도 아파치나 MySQL 및 기타 데몬들의 로그파일 때문인것 같습니다. 먼저 /var 안에 로그 파일들을 기록 하는 데몬들을 하나씩 리스타트 해보시기를 권해 드립니다. ;

제 생각엔 로그가 가장 많이 쌓이는 아파치가 유력합니다..

자세한 내용은 다음 링크를 참고 하세요..

http://bbs.kldp.org/viewtopic.php?t=19446

;

cjh의 이미지

그런 질문이 있었다 생각을 해 보니 위 링크에 제가 쓴 글도 있군요. :)

하여튼 가장 좋은 방법은 umount/mount 하는 겁니다. /var면 리부팅해야겠네요...

--
익스펙토 페트로눔

advanced의 이미지

mount/unmount 하면 다시 돌아온다고 하니

umount 하면 그때 버퍼에 있는 것을 모두 쏟아내서 그런건가요?

그럼 sync 로 동기화 해보면 어떨까요?

그냥 한번 여쭈어 본겁니다

- advanced -

cjh의 이미지

그게.. 열려 있는 파일을 없애거나 변경해도 reference count는 남습니다. 하지만 파일이 없어지거나 변경되면 현재 열려 있는 파일을 찾아서 제대로 닫을 방법이 없죠(이름이 없으니까 접근할 수가 없죠) 그래서 지우거나 하면(이름 바꾸는건 될 것 같습니다. logrotate/newsyslog가 돌아가는걸 보면...) 파일 시스템 내에서는 완전히 없어진 게 아니라 공간은 할당된 채로 남아 있는데 그걸 해제할 방법이 없는 거죠. 일종의 좀비 파일이라고나 할까요...

언마운트하면 그런 reference count가 강제로 사라지니까 다시 붙일 때 빈 공간이 돌아오게 됩니다. sync는 현재 디스크 버퍼에 쓰지 않은 걸 쓰라는 거니까 관련이 없겠죠.

--
익스펙토 페트로눔

박영선의 이미지

리눅스는 아니었지만 전에 프비에서 그런적이있었습니다.

제경우에는 재부팅해도 그대로였었습니다.

du로 확인하니 멀쩡하길래 그냥 포기하고 살다보니 어느날인가는 또 멀쩡히 df에서도 실제크기 그대로 나오더군요...

프비 3.3인가 3.44인가였었던거같은데, 요즘은 그런걸본적이없어서 버그가 잡힌건 아닌가했었습니다.

^^;;

pynoos의 이미지

재현을 해볼까요?

# ls > ll.txt  
# tail -f ll.txt &
# rm -f ll.txt
# lsof -n | grep tail
tail       2231     root  cwd    DIR        3,5      4096    389407 /root
tail       2231     root  rtd    DIR        3,5      4096         2 /
tail       2231     root  txt    REG        3,5     30940    357500 /usr/bin/tail
tail       2231     root  mem    REG        3,5    471781   1022153 /lib/ld-2.2.2.so
tail       2231     root  mem    REG        3,5       181    454288 /usr/lib/locale/ko_KR.euckr/LC_IDENTIFICATION
tail       2231     root  mem    REG        3,5        13    259597 /usr/lib/locale/ko_KR.euckr/LC_MEASUREMENT
tail       2231     root  mem    REG        3,5        46    454290 /usr/lib/locale/ko_KR.euckr/LC_TELEPHONE
tail       2231     root  mem    REG        3,5       117   1038356 /usr/lib/locale/ko_KR.euckr/LC_ADDRESS
tail       2231     root  mem    REG        3,5        52   1038361 /usr/lib/locale/ko_KR.euckr/LC_NAME
tail       2231     root  mem    REG        3,5        24    259601 /usr/lib/locale/ko_KR.euckr/LC_PAPER
tail       2231     root  mem    REG        3,5        46    389390 /usr/lib/locale/ko_KR.euckr/LC_MESSAGES/SYS_LC_MESSAGES
tail       2231     root  mem    REG        3,5       280    373168 /usr/lib/locale/ko_KR.euckr/LC_MONETARY
tail       2231     root  mem    REG        3,5      2130    373169 /usr/lib/locale/ko_KR.euckr/LC_TIME
tail       2231     root  mem    REG        3,5        44    486736 /usr/lib/locale/ko_KR.euckr/LC_NUMERIC
tail       2231     root  mem    REG        3,5   5634864    113595 /lib/i686/libc-2.2.2.so
tail       2231     root  mem    REG        3,5    296548    373166 /usr/lib/locale/ko_KR.euckr/LC_COLLATE
tail       2231     root  mem    REG        3,5    553468    373167 /usr/lib/locale/ko_KR.euckr/LC_CTYPE
tail       2231     root    0u   CHR      136,3                   5 /dev/pts/3
tail       2231     root    1u   CHR      136,3                   5 /dev/pts/3
tail       2231     root    2u   CHR      136,3                   5 /dev/pts/3
tail       2231     root    3r   REG        3,5       136    391136 /root/ll.txt (deleted)

맨아래에 보면 /root/ll.txt 가 deleted 라고 되어 있는게 있습니다.

lsof -n | grep deleted

이렇게 찾아서 디렉토리상에서는 지워졌지만 프로세스상에서 레퍼런스 카운트가 존재하는 놈을 찾아 그 프로세스들을 리스타트 시켜주면 될 것 같습니다.

jemiro의 이미지

df 와 du의 사용량 차이가 보이는 원인중 하나가
/var/log/lastlog 의 기록 방법일지도 모릅니다.

만약 uid 가 9000번인 user가 로그인을 할경우

uid * sizeof(struct lastlog) 의 값을 offset으로
fseek으로 파일포인터를 이동후 저장을 합니다.

이때 uid가 클경우 실제 파일사이즈 보다 큰 offset으로
데이터가 저장되는데 그결과
df에는 offset만큼 파일이 사용하고 있는것으로 나오지만

du로 보면 실제 데이터를 저장한 공간만
사용량으로 보여줍니다.

jw0717의 이미지

음 아래글을 읽어봤는데 무슨 내용인지 모르겠더군요.

혹시 아래글같은 연유로 그런게 아닌지..

혹시나 해서 올려봅니다....

-----------------아래----------------------------------

"du -s /filesystem_path"를 실행시킨 결과값을 전체 불럭수에서  뺀 값과 "df"를 이용하여 얻은 자유 블럭 값을 비교하는  경우, "du"를 이용하여 얻은 자유 블럭의 수는  "df"를 이용하여 얻은 자유 블럭의 수보다 크다.  예를 들자면:

% du -s /tmp
12920 /tmp
% df /tmp
Filesystem 512-blocks Free %Used Iused %Iused Mounted on
/dev/hd3 57344 42208 26% 391 4% /tmp
따라서 "df"를 통하여 얻은 값에서  "du"를 통하여 얻은 값을 빼면 다음과 같은 잘못된 값을  얻게 된다.

- =
57344 - 12920 = 44424
위의 예에서 보는 바와 같이 44424는 42208보다 큰 값이다.  이렇게 값이 서로 다른 것은 "du"와 "df"가  각각 디스크에 대한 계산을 달리 하는데 기인한다.  그러면, 각각의 명령어에 대한 적용방법이 어떻게 다른가를  살펴 보도록 한다.

du -sk
"du -sk"는 파일트리(file tree)를 따라 이동하면서,  stat()라는 시스템 호출을 이용하여 얻은  각각의 디렉토리,  심링크(symlink)및 파일에 할당된 블럭의 수를 더한다. 바로  이러한 방법을 통하여 "du"는 총 값을 계산하게 되는  것이다.

df
"dt"는 파일시스템의 디스크 블럭 할당 지도(1) 들을 조회하여  총값및 자유블럭의 수를 산출한다.

왜 이들 숫자들은 더하여 얻어지는 것이 아닌가?
파일시스템은 자신의 자료를 기록하기 위하여 자신의  파일시스템내에 약간의 디스크 블럭들을 할당한다; 이런  자료들을 메타자료(2) 라고 한다. 이러한  메타자료들은 사용자 수준의 프로그램들은 거의 감지하지  못하며, 이러한 자료들의 예는 inode, 디스크지도(3) , 간접블럭들(4) 및  수퍼블럭들(5) 들이다.

"du"는 이러한 파일시스템 메타자료들을 인지하지 못하는  사용자 수준의 프로그램이다. "df"는 파일시스템의  디스크 할당지도를 조회하고, 따라서 파일시스템 메타자료들을  인식한다. 즉 "df"는 실제의 파일시스템 통계값을  얻을 수 있는 반면에, "du"는 파일시스템의 부분만을  조회하는 것이다. 예를 들어, n개의 4MB크기를 가지는  JFS파일시스템이 frag=4096 그리고 nbpi=4096이라는  값을 가지고 생성되는 경우, 다음의 메타자료들이 할당된다:

1 4k block for the LVM
2 4k super blocks
2 4k blocks for disk maps
2 4k blocks for inode maps
2 4k blocks for .indirect
32 4k blocks for inodes
-------------------------
41 4k blocks for meta data on an empty 4M file system
# df /foo
8 /foo
즉 이러한 빈 파일시스템에 대하여 "du"를 적용하는 경우  8개의 512바이트 블럭들이 루트 디렉토리에 의해 사용되고  있다고 보여지게 된다.

"du"의 결과값이 "df"의 결과값과 일치되기 위해서는,  메타자료의 값을 "du"의 결과값에 더하여야 한다. 이를  위해서는 먼저, 42개의 4K바이트의 블럭을 512바이트의  단위로 바꾼다:

41 * 8 = 328
328(meta data) + 8(from du) = 336
즉 이러한 빈 파일시스템에 할당된 총 336개의 512바이트  블럭들이 있는 것이다. 그러므로:

8192(total blocks) - 336(used from du + meta data) = 7856
즉 이렇게 얻은 값은 "df"의 자유블럭의 값과 일치한다.  이러한 계산은 빈 파일시스템에 대하여서는 매우 쉽다고  할 수 있다. 하지만, 빈 파일시스템이 아닌 경우에는,  파일간접블럭(6) 들에 대한  계산이 필요하게 되므로, 그 계산자체가 매우 어렵고 또한  비현실적일 수 있다.

결론적으로 "du -s"는 파일과 디렉토리들에 할당된  디스크 블럭들의 수를 알려주는 것이며, "df"는  해당 파일시스템의 실제 할당상태에 대한 내용을  알려주는 것이다. 이러한 실제 할당상태란  사용자 자료(파일및 디레토리들)들에 추가하여  메타자료를 포함하는 것을 말한다.

eungkyu의 이미지

jw0717 wrote:
음 아래글을 읽어봤는데 무슨 내용인지 모르겠더군요.

혹시 아래글같은 연유로 그런게 아닌지..

혹시나 해서 올려봅니다....

대충 읽어보니, 한 블럭 최소 크기가 있기 때문에 차이가 있다는 얘기같습니다. 그치만, 지금 말하고 있는 문제는 그 문제가 아닌 듯 합니다. 열린 파일을 지웠을 때 OS 내부에 있는 ref count가 0이 되지 않기까지 파일은 실제로 지워지지 않지만, ls같은 걸로는 볼 수가 없기 때문에 du와 df가 다르다고 하는 것이네요.

df가 실제 디스크를 검사하는 반면 du는 파일 목록을 보고 더하기 때문에 지워졌지만 실제로 있는 파일은 체크되지가 않겠죠.

그래서 이것을 해결하기 위해서는 lsof로 지워진 (거대한 - 주로 로그) 파일을 열고 있는 프로그램을 보고 그 프로그램을 재시작 하든지 하는 방법으로 해결을 보라는 것입니다.

권순선의 이미지

pynoos wrote:
lsof -n | grep deleted

이렇게 찾아서 디렉토리상에서는 지워졌지만 프로세스상에서 레퍼런스 카운트가 존재하는 놈을 찾아 그 프로세스들을 리스타트 시켜주면 될 것 같습니다.


이대로 해서 살펴보니 mysqld가 제가 예전에 지워버렸던 파일을 붙잡고 계속해서 뭔가를 쓰고 있었던 것 같습니다.

그래서 mysqld를 정상적으로 종료하고....물론 이 과정에서도 단순히 /etc/init.d/mysql stop만 수행한 것이 아니라 mysqladmin shutdown 으로 수행해서 좀더 확실하게 mysqld를 종료한 뒤에 df로 체크를 해 보니 드디어 제대로 나오네요. mysql관리를 하면서 그냥 /etc/init.d/mysql stop 만 수행하고...제대로 종료되지 않은 것들은 mysqladmin이 종료하는 것을 기다리지 못하고(시간이 오래 걸리더군요) 그냥 아무 생각없이 killall로 수행을 했던 것이 문제였던 것 같습니다. 좋은 교훈을 얻었군요. :-)

감사합니다....

권순선의 이미지

흠...거의 두달 전에 질문했던 내용인데 다시 비슷한 현상이 발생하여 추가 질문을 올립니다.

이번에도 /var 디렉토리가 99%까지 차 있어서(df 로 확인) /var 에서 du 로 확인해 보니 실제로는 50% 정도만 차 있더라구요.

그래서 lsof -n | grep deleted 으로 확인해 보니 의심이 갈만한 부분이 없었습니다. 지난번에 문제가 되었던 mysql 쪽도 없었고, 전혀 관련없는 디렉토리인 /tmp 아래에 apache 가 뭔가 쓰다가 만 흔적이 있어 처리하고 나니 lsof -n | grep deleted 를 수행했을 때는 아무런 출력이 없는 상태가 되었습니다.

그렇게 했는데도 여전히 df 로 확인했을 때는 99%가 차 있는 것으로 나오더군요. 그래서 일단은 서버를 리부팅했고, 지금은 정상적으로 나오는데 아무래도 근본적인 원인을 찾아보아야 할 것 같습니다.

어디 짚이는 부분이 있으신 분들은 글을 좀 올려 주세요.... :-)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.