<commit_before>---
layout: post
title: 'du与df的区别'
date: 2018-06-12
author: smallsat
categories: linux 运维
tags: linux 运维 
---

背景：一天，在家休息中，忽然经理告知服务器储存已经跑到了90%。由于本台服务器运行着一个大型的日志系统，于是打开终端，进入了远程服务器，将日志进行了删除。之前做了一个定时任务，定时删除15天之前的日志（按理说已经不会出现问题，此处已经伏笔。）。

在处理完毕后，关闭电脑准备赴约的时候，经理告知还会收到报警。不解其中的原因，赶忙进入终端，在根目录查询占用情况。
```cmd
du -h --max-depth=1; #以可视的文档展示文件夹大小，指定目录的深度为1，否则将递归展示
```
运行命令后发现总的磁盘占用没超过10%，可是还是再收到磁盘占用的报警。

在其他人员的帮助下，发现是我删除大文件后产生了大量的进程，在使用`df`指令进行统计的时候还是占用超过90%

# 相关资料

##  命令介绍
1.  `du`全称为：Disk Usage
`du`命令会对待统计的文件逐个调用`fastat`，获取文件大小。它的数据基于实际存在的文件获取，可以跨分区进行操作，但是如果文件比较多的话，`du`的速度就会变得慢

2. `df`全称为：Disk Free
`df`命令使用`statfs`这个系统调用，直接读取分区的超级块信息，获取分区的使用情况。它的数据是基于分区**元数据**，所以只能针对整个分区。由于`df`直接读取超级块信息，所以访问速度很快，不受文件数量影响。

## `du`与`df`不一致的原因

常见的`df`和`du`不一致情况就是文件删除的问题。当一个文件被删除后，在文件系统目录中已经不可见了，所以`du`就不会再统计它了。然而，如果此时还有运行的进程持有这个已经被删除了的文件的句柄，那么这个文件就不会真正在磁盘中被删除，分区超级块中的信息也就不会更改。这样`df`仍旧会统计这个被删除了的文件。

## 情况复现

查看当前的使用
```cmd
df -h /dev/sda10
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   21G   49G   30% /home
```
新建一个1GB的大文件
```cmd
dd if=/dev/zero of=myfile.iso bs=1024k count=1000
记录了1000+0 的读入
记录了1000+0 的写出
1048576000字节(1.0 GB)已复制，24.0954 秒，43.5 MB/秒
```
此时的分区sda10使用情况
```cmd
df -h /dev/sda10
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   22G   48G   31% /home
```
使用`su`查询
```cmd
du -sh /home/***/Documents/test/
1001M	/home/***/Documents/test/
```
将文件载入进程并删除
```cmd
tail -f myfile.iso &
[1] 10364
rm -f myfile.iso
```
查看文件是否存在于进程
```cmd
lsof | grep myfile.iso
tail      10364               smallsat    3r      REG               8,10 1048576000    3022143 /home/***/Documents/test/myfile.iso (deleted)
```
再次用`su`和`sf`进行统计
```cmd
du -sh /home/***/Documents/test/
4.0K	/home/***/Documents/test/

df -h /home/***/Documents/test/
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   22G   48G   31% /home
```
可以看出`du`已经不再统计该文件了，而`df`还是继续统计

下面关闭进程后进行统计
```cmd
kill 10364
#查看是否还存在与进程中
lsof | grep myfile.iso
#df统计
df -h /home/***/Documents/test/
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   21G   49G   30% /home
```
可以看出已经恢复了。
## 总结
1. 在查看硬盘的使用情况的时候使用`du`和`df`双重查看，避免出现两种统计差距过大。
2. 如果出现差距很大的情况，注意查看进程，停止相关进程。方法是`lsof。
3. 可以使用清空文件的方式，`echo>filename`。
4. 对于日志文件使用如下顺序：改名、清空、删除。
5. 除了rm外，还可以使用间接删除的方式，比如使用`gzip`命令，该命令会删除原文件，不过该文件还是无法解决进程占用的问题。

后续：此问题连锁引起的其他问题后续再聊<commit_msg>du与df的区别<commit_after>---
layout: post
title: 'du与df的区别'
date: 2018-06-12
author: smallsat
categories: linux 运维
tags: linux 运维 
---

背景：一天，在家休息中，忽然经理告知服务器储存已经跑到了90%。由于本台服务器运行着一个大型的日志系统，于是打开终端，进入了远程服务器，将日志进行了删除。之前做了一个定时任务，定时删除15天之前的日志（按理说已经不会出现问题，此处已经伏笔。）。

在处理完毕后，关闭电脑准备赴约的时候，经理告知还会收到报警。不解其中的原因，赶忙进入终端，在根目录查询占用情况。
```cmd
du -h --max-depth=1; #以可视的文档展示文件夹大小，指定目录的深度为1，否则将递归展示
```
运行命令后发现总的磁盘占用没超过10%，可是还是再收到磁盘占用的报警。

在其他人员的帮助下，发现是我删除大文件后产生了大量的进程，在使用`df`指令进行统计的时候还是占用超过90%

# 相关资料

##  命令介绍
1.  `du`全称为：Disk Usage
`du`命令会对待统计的文件逐个调用`fastat`，获取文件大小。它的数据基于实际存在的文件获取，可以跨分区进行操作，但是如果文件比较多的话，`du`的速度就会变得慢

2. `df`全称为：Disk Free
`df`命令使用`statfs`这个系统调用，直接读取分区的超级块信息，获取分区的使用情况。它的数据是基于分区**元数据**，所以只能针对整个分区。由于`df`直接读取超级块信息，所以访问速度很快，不受文件数量影响。

## `du`与`df`不一致的原因

常见的`df`和`du`不一致情况就是文件删除的问题。当一个文件被删除后，在文件系统目录中已经不可见了，所以`du`就不会再统计它了。然而，如果此时还有运行的进程持有这个已经被删除了的文件的句柄，那么这个文件就不会真正在磁盘中被删除，分区超级块中的信息也就不会更改。这样`df`仍旧会统计这个被删除了的文件。

## 情况复现

查看当前的使用
```cmd
df -h /dev/sda10
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   21G   49G   30% /home
```
新建一个1GB的大文件
```cmd
dd if=/dev/zero of=myfile.iso bs=1024k count=1000
记录了1000+0 的读入
记录了1000+0 的写出
1048576000字节(1.0 GB)已复制，24.0954 秒，43.5 MB/秒
```
此时的分区sda10使用情况
```cmd
df -h /dev/sda10
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   22G   48G   31% /home
```
使用`su`查询
```cmd
du -sh /home/***/Documents/test/
1001M	/home/***/Documents/test/
```
将文件载入进程并删除
```cmd
tail -f myfile.iso &
[1] 10364
rm -f myfile.iso
```
查看文件是否存在于进程
```cmd
lsof | grep myfile.iso
tail      10364               smallsat    3r      REG               8,10 1048576000    3022143 /home/***/Documents/test/myfile.iso (deleted)
```
再次用`su`和`sf`进行统计
```cmd
du -sh /home/***/Documents/test/
4.0K	/home/***/Documents/test/

df -h /home/***/Documents/test/
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   22G   48G   31% /home
```
可以看出`du`已经不再统计该文件了，而`df`还是继续统计

下面关闭进程后进行统计
```cmd
kill 10364
#查看是否还存在与进程中
lsof | grep myfile.iso
#df统计
df -h /home/***/Documents/test/
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda10       73G   21G   49G   30% /home
```
可以看出已经恢复了。
## 总结
1. 在查看硬盘的使用情况的时候使用 `du` 和 `df` 双重查看，避免出现两种统计差距过大。
2. 如果出现差距很大的情况，注意查看进程，停止相关进程。方法是 `lsof`。
3. 可以使用清空文件的方式，`echo>filename`。
4. 对于日志文件使用如下顺序：改名、清空、删除。
5. 除了rm外，还可以使用间接删除的方式，比如使用`gzip`命令，该命令会删除原文件，不过该文件还是无法解决进程占用的问题。

后续：此问题连锁引起的其他问题后续再聊
{'fraction_non_alphanumeric': 0.14981517721243748, 'fraction_numerical': 0.0669710806697108, 'mean_word_length': 4.311778290993072, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2999452', 'n_tokens_mistral': 3451, 'n_tokens_neox': 3648, 'n_words': 360}