下面的问题来自于一个很不错的QQ群记录:
关于linux和unix磁盘档案系统中inode和block的相关知识可以参照【鸟哥的linux私房菜】中“linux磁盘与硬件管理”那一章。
关于空洞文件致使拷贝后大小变化的原因可参照博文“件空洞产生的原因分析”。
内容:
早上有同事反映rsync目的的文件总大小比源上的小100M,这个可能是什么情况?目标机上有几个文件的时间戳是1周前的,我们备份放置方式是0-7的周目录,因为他删掉了那几个旧文件我也没法查看.
备份命令是
rsync -ac --numeric-ids -b --backup-dir="xxx"
--password-file=xxx user@IP::module dest
龙猫_Lee 10:13:01
第一感觉 就是有传送失败的
我晕晕 10:14:31
我检查过,log没异常
永恒 10:28:32
两个机器分区参数都完全一样吗?
我晕晕 10:32:17
都是ext3读写方式
我晕晕 10:32:24
其他还有什么参数?
永恒 10:38:05
tune2fs 分区 -l 看下比对是否完全一样
永恒 10:38:15
主要是块大小
龙猫_Lee 10:39:54
永恒的意思 是说可能块分大了 所以 会有空间浪费吗?
我晕晕 10:40:38
这个有关系嘛?
5h@dOw 10:41:20
block size呢?
我晕晕 10:41:29
都是4K
永恒 10:43:03
还有个每组块数
我晕晕 10:44:05
Blocks per group: 32768
都一样
我为SUN狂.cc 10:44:10
find查下每个文件的修改时间和大小。
永恒 10:44:16
Inodes per group
永恒 10:44:36
全部一样就可以排除这个问题
我晕晕 10:44:51
就是目地机上有几个文件时间不是新的,但是已经被同事删掉了
永恒 10:44:52
以前都一致,今天发现不一致了,应该不是这问题
永恒 10:45:21
同步日志没问题就没事
我晕晕 10:45:25
inode per group有区别
我晕晕 10:45:38
Inodes per group: 32768 | Inodes per group 16384
5h@dOw 10:46:48
这个有区别有啥影响?
我为SUN狂.cc 10:47:53
比如一个2K的文件,前面是占用32K,后面是占用16K
我为SUN狂.cc 10:48:08
所以du结果不一定准确。
永恒 10:48:26
这个参数不一样,导致分区后挂载显示的分区容量不一样
我晕晕 10:48:34
哦
我晕晕 10:48:56
那照理说如果是这样的话,至少所有文件的时间戳应该是更新的呀
我为SUN狂.cc 10:49:06
如果你不相信rsync或者你的脚本,你可以自己写个脚本校验两边的文件大小和修改时间。
龙猫_Lee 10:49:06
我为SUN狂.cc
10:47:02
比如一个2K的文件,前面是占用32K,后面是占用16K
所以du结果不一定准确。==》我感觉 像是block size的问题……
我晕晕 10:49:38
那个命令取文件大小比较准确?
龙猫_Lee 10:50:01
inode per group 这个 会有这么大的差别吗?
我为SUN狂.cc 10:51:07
小文件多的话差很大,每个文件都可能会差16K
我为SUN狂.cc 10:51:29
find取的是文件大小,不是文件占用空间大小
龙猫_Lee 10:52:02
好底层……
我晕晕 10:52:25
呃,
我为SUN狂.cc 10:52:47
10:52:30#tp#~> find -maxdepth 1 -name a -printf
"%s %p\n"
2 ./a
10:52:33#tp#~> du -h a
4.0K a
10:52:38#tp#~>
5h@dOw 10:53:00
听不懂。。
龙猫_Lee 10:53:37
2字节 占用4k ?
我为SUN狂.cc 10:53:39
默认每个block是4K。就是说就算你文件里面只有一个字符,也要占用4K空间。
我晕晕 10:53:42
文件大小就是水量,空间大小就是容器大小,差不多这个意思吧
我为SUN狂.cc 10:54:00
是的,这个瓶子很空,但是还是占用了一个瓶子。
龙猫_Lee 10:54:19
inodes per group 这个选项何意?
龙猫_Lee 10:54:28
google 木有查到……
我为SUN狂.cc 10:54:52
就是每个block的大小
龙猫_Lee 10:55:17
不是block_size ?
igi 10:55:23
文件大小就是水量,这个水量有可能比瓶子本身还大,嘿嘿
我为SUN狂.cc 10:56:15
不会比瓶子大,会占用多个瓶子
igi 10:56:51
我说的是空洞文件之类的,应该不会占用多个瓶子吧
我晕晕 10:57:14
哦?
龙猫_Lee 10:57:43
空洞也会把
我为SUN狂.cc 10:57:52
http://segmentfault.com/question/3/tune2fs列出的inode-blocks-per-group是什么意思
igi 10:57:52
瓶子是实际空间,文件大小,其实不一定是真实的,它也可以是假的
龙猫_Lee 10:57:53
du会检测到空洞
5h@dOw 10:58:00
什么是空洞?
龙猫_Lee 10:58:07
没内容
5h@dOw 10:58:26
这个也会占用瓶子?
我晕晕 10:58:38
就是lseek到某个位置然后点东西
5h@dOw 10:58:38
我最近也遇到一个棘手的问题。。
龙猫_Lee 10:58:39
我理解成 气泡
我晕晕 10:58:48
然后这个文件就会貌似很大
5h@dOw 10:59:30
df -h 看到磁盘已经使用 了80G, 可是 du -sh ./*
那个目录下面的所有文件的大小加起来还不到1G,,
龙猫_Lee 10:59:44
句柄
龙猫_Lee 10:59:55
可能是句柄没有释放
5h@dOw 11:00:09
句柄?
龙猫_Lee 11:00:18
lsof |grep deleted
5h@dOw 11:01:07
确实有区多已经deleted的文件。。
5h@dOw 11:01:16
但是去目录下看到时候,已经不存在了。。
5h@dOw 11:01:27
这怎么回事。。。。
我为SUN狂.cc 11:01:32
杀掉那个进程
我为SUN狂.cc 11:01:43
进程没结束是不会释放那些空间的
5h@dOw 11:02:18
确实会释放,,可是,,这个程序是个生产的程序,,
5h@dOw 11:02:32
下次跑得时候还会这样。。。
5h@dOw 11:02:36
难道是程序本身有问题?
No.one 11:02:36
将对应的服务重启即可
龙猫_Lee 11:02:58
这就得看文件是怎么生成的了吧
5h@dOw 11:03:03
是删除没删除干净?还是怎么?
No.one 11:03:03
实在不行重启机器,保证释放
龙猫_Lee 11:03:17
不是
igi 11:03:33
程序设计的缺陷吧,如果你的程序设计成能释放这个句柄,重新生成一个文件,那就没这个事了
5h@dOw 11:04:19
意思就是,生成那个文件的进程?
龙猫_Lee 11:04:35
不是 应该是使用
龙猫_Lee 11:04:45
不过 有可能那个文件也是程序生成的
我为SUN狂.cc 11:05:10
设计问题
5h@dOw 11:05:45
是有个进程在不停的在写文件
我为SUN狂.cc 11:06:08
应该这样:给个信号,然后程序内部把原来日志文件改名,然后创建新的日志文件。
5h@dOw 11:09:04
我觉得也是,
5h@dOw 11:09:09
程序有问题。。
5h@dOw 11:09:26
那个进程一重启,立马空间就释放了。
我为SUN狂.cc 11:10:59
也不算是有问题,就是当时写的时候没考虑到这个问题,少了功能。
我晕晕 11:18:35
生成一个空洞文件,结果一拷贝,block数目翻倍了
我晕晕 11:18:53
File: `bb'
Size: 16384 Blocks:
32
我晕晕 11:19:00
File: `file.hole'
Size: 16384 Blocks:
8
glqaizl 11:20:13
请教下 文件所占的block数 是用什么命令看到的~?
我为SUN狂.cc 11:20:22
stat
glqaizl 11:20:28
3x
我晕晕 11:25:21
空洞是不占统计字节的,如果空洞大于1个block的话
我为SUN狂.cc 11:25:31
晕晕,你的空洞文件怎么创建的?
我晕晕 11:25:42
lseek然后write
我晕晕 11:25:53
apue上有例子
我为SUN狂.cc 11:27:12
shell不行?那就算了
我晕晕 11:27:33
#include
#include
#include
#include
#define FILE_MODE (S_IRUSR | S_IWUSR |
S_IRGRP | S_IROTH)
main(){
int
fd;
off_t
offset = 16383;
char buf[]
= "A";
if((fd=creat("file.hole",FILE_MODE))<0)
{
printf("create error\n");
exit(1);
}
if(lseek(fd,offset,SEEK_SET) != offset)
{
printf("seek error\n");
exit(1);
}
if(write(fd, buf,1)!=1)
{
printf("write
error\n");
exit(1);
}
exit(0);
}
我晕晕 11:27:52
然后 cc下
我为SUN狂.cc 11:27:59
懒得编译
龙猫_Lee 11:28:03
我买了apue
我为SUN狂.cc 11:28:16
我知道这个,稀疏文件
海.time 11:31:59
sun写shell跟perl都写习惯了,对于要经过编译的表示很不屑哈
【提示:此用户正在使用Q+ Web:http://web2.qq.com/】
我晕晕 11:32:44
海博士解释下
生成一个空洞文件,结果一拷贝,block数目翻倍了
File: `bb'
Size: 16384 Blocks: 32
File: `file.hole'
Size: 16384 Blocks: 8
海.time 11:33:14
话说,perl里没有seek类似的功能吗?
龙猫_Lee 11:33:15
减少了吧
我晕晕 11:33:41
不知道,没用过
我晕晕 11:33:53
bb是被拷贝的
海.time 11:35:41
不晓得哈,先去吃饭了,回来查下apue:)
我为SUN狂.cc 11:37:16
我第一个接触的就是basic,所以不喜欢编译,尤其是C,pascal程序员泪奔而过
我为SUN狂.cc 11:38:05
你cp file.hole bb?
我为SUN狂.cc 11:38:16
你seek了24个block?
我为SUN狂.cc 11:40:09
从空洞文件变成普通文件了吧
我为SUN狂.cc 11:40:21
默认16384在你那是32个block?
igi 11:49:08
用dd就可以创建空洞文件啊,不用自己写个程序,折腾啊
我为SUN狂.cc 11:49:34
d
我为SUN狂.cc 11:49:37
dd
我为SUN狂.cc 11:49:45
dd用seek?不行吧
igi 11:49:59
为啥不行,就是有seek参数
我为SUN狂.cc 11:50:18
创建出来的是普通文件
igi 11:51:13
igi@arch /tmp/test $ ls
igi@arch /tmp/test $ dd if=/dev/zero of=file2 bs=1024k
seek=100 count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.0071954 s, 1.5 GB/s
igi@arch /tmp/test $ ls -lh file2
-rw-r--r-- 1 igi igi 110M Feb 8 11:50
file2
igi@arch /tmp/test $ du -sh file2
10M file2
我为SUN狂.cc 11:51:30
见鬼,刚才不行,现在好了
igi 11:53:11
igi@arch /tmp/test $ touch file
igi@arch /tmp/test $ truncate -s 100M file
igi@arch /tmp/test $ ls -lh file
-rw-r--r-- 1 igi igi 100M Feb 8 11:53
file
igi@arch /tmp/test $ du -sh file
0 file
龙猫_Lee 11:54:01
我靠~!
我为SUN狂.cc 11:56:18
我这cp不会变化
我为SUN狂.cc 11:56:46
11:55:35#tp#~> cp aa cc
11:55:40#tp#~> cp bb dd
11:55:46#tp#~> stat aa|sed -n 2p
大小:48384 块:72 IO 块:4096 普通文件
11:55:52#tp#~> stat bb|sed -n 2p
大小:48384 块:40 IO 块:4096 普通文件
11:55:56#tp#~> stat cc|sed -n 2p
大小:48384 块:72 IO 块:4096 普通文件
11:55:58#tp#~> stat dd|sed -n 2p
大小:48384 块:40 IO 块:4096 普通文件
11:56:01#tp#~>
我为SUN狂.cc 11:57:10
bb是seek的
igi 11:59:45
我晕晕
11:32:44
海博士解释下
生成一个空洞文件,结果一拷贝,block数目翻倍
我记得cp现在又参数针对空洞文件的拷贝, --sparse
不同的设置可能让cp针对空洞文件的处理不同
igi@arch /tmp/test $ ls -lh file;du -sh file
-rw-r--r-- 1 igi igi 100M Feb 8 11:53
file
0 file
igi@arch /tmp/test $ cp file newfile; ls -lh newfile; du -sh
newfile; stat file newfile; rm -f newfile
-rw-r--r-- 1 igi igi 100M Feb 8 11:58
newfile
0 newfile
File: `file'
Size: 104857600 Blocks: 0
IO Block: 4096
regular file
Device: 11h/17d Inode: 41469 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/
igi) Gid:
( 1000/ igi)
Access: 2012-02-08 11:56:59.161769830 +0800
Modify: 2012-02-08 11:53:01.245117547 +0800
Change: 2012-02-08 11:53:01.245117547 +0800
Birth: -
File: `newfile'
Size: 104857600 Blocks: 0
IO Block: 4096
regular file
Device: 11h/17d Inode: 41503 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/
igi) Gid:
( 1000/ igi)
Access: 2012-02-08 11:58:05.865099131 +0800
Modify: 2012-02-08 11:58:05.941765793 +0800
Change: 2012-02-08 11:58:05.941765793 +0800
Birth: -
igi@arch /tmp/test $ cp --sparse=never file newfile; ls -lh
newfile; du -sh newfile; stat file newfile; rm -f newfile
-rw-r--r-- 1 igi igi 100M Feb 8 11:58
newfile
100M newfile
File: `file'
Size: 104857600 Blocks: 0
IO Block: 4096
regular file
Device: 11h/17d Inode: 41469 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/
igi) Gid:
( 1000/ igi)
Access: 2012-02-08 11:56:59.161769830 +0800
Modify: 2012-02-08 11:53:01.245117547 +0800
Change: 2012-02-08 11:53:01.245117547 +0800
Birth: -
File: `newfile'
Size: 104857600 Blocks: 204800
IO Block: 4096
regular file
Device: 11h/17d Inode: 41505 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/
igi) Gid:
( 1000/ igi)
Access: 2012-02-08 11:58:27.128431178 +0800
Modify: 2012-02-08 11:58:27.195097841 +0800
Change: 2012-02-08 11:58:27.195097841 +0800
Birth: -
我为SUN狂.cc 12:04:26
12:03:44#tp#~> \cp --sparse=never aa ee;stat
ee|sed -n 2p
大小:48384 块:96 IO 块:4096 普通文件
12:04:01#tp#~> \cp --sparse=always aa ee;stat
ee|sed -n 2p
大小:48384 块:0 IO 块:4096
普通文件
12:04:08#tp#~>
我为SUN狂.cc 12:05:35
12:04:58#tp#~> rm ee;\cp --sparse=never bb
ee;stat ee|sed -n 2p
大小:48384 块:96 IO 块:4096 普通文件
12:05:02#tp#~> rm ee;\cp --sparse=always bb
ee;stat ee|sed -n 2p
大小:48384 块:0 IO 块:4096
普通文件
12:05:13#tp#~> stat bb|sed -n 2p
大小:48384 块:40 IO 块:4096 普通文件
海.time2012-02-08 12:46:59
回来了,看到sun跟igi的,学习了
5h@dOw(327106806) 13:12:52
http://hi.baidu.com/ops_bd/blog/item/6fc1e4f2cc08c136bd31099d.html
我晕晕
13:26:42
学习下,我也是arch貌似truncate生成的块不为0
> truncate -s 16M file.hole
> ls -l file.hole
-rw-r--r-- 1 root root 16777216 Feb 7 21:14
file.hole
> stat file.hole |sed -n 2p
Size: 16777216 Blocks: 8
IO Block: 4096
regular file
> truncate --version
truncate (GNU coreutils) 8.5
> du --version
du (GNU coreutils) 8.5
5h@dOw(327106806) 13:31:34
scp空洞文件到其它机器,占用磁盘空间好像还是0哎。。
5h@dOw(327106806) 13:35:17
大虾们。。为啥阿〉?
5h@dOw(327106806) 13:39:17
# ll -sh test.tt
0 -rw-r--r-- 1 root root 3.0M Feb 8 13:31
test.tt
5h@dOw(327106806) 13:39:26
# du -sh ./test.tt
0 ./test.tt
5h@dOw(327106806) 13:40:56
这个是不是就是空洞文件??