linux拷贝文件大小不一样,关于拷贝或远程拷贝文件后大小不一致的问题分析

下面的问题来自于一个很不错的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

这个是不是就是空洞文件??

当你通过 `scp`(secure copy protocol)传输文件时发现文件大小符的情况,可能是由以下几个原因导致的。下面将详细介绍可能的原因及对应的解决办法。 --- ### 一、可能导致问题的因素 #### 1. 源文件和目标机器上文件系统的块大小差异 - 当你从一台机器复制文件到另一台机器时,如果两者的文件系统使用的存储块大小一样,则可能会造成最终展示出来的文件大小略有差别。尽管物理数据并未丢失损坏,但由于计量单位的同,看起来文件似乎变大了是缩小了。 #### 2. 文件权限设置当 如果目标端存在特殊的权限限制者用户组配置错误,在某些情况下也可能影响SCP操作过程中是否能完整地复制整个文件内容。 #### 3. SCP 过程中断 SCP是一个基于SSH协议的安全拷贝工具,若网络连接稳定者其他外界因素干扰到了正常的传输流程,就很可能致使部分数据未成功发送过去,进而使得接收方接收到的数据小于原文件的真实尺寸。 #### 4. 编码转换的问题 对于文本类型的文档来说,由于同平台间换行符标准有所区别(Linux 使用 LF, Windows 则采用 CRLF),所以在跨平台使用 SCP 移动这类文件的时候容易引发一些必要的改动,从而改变原本应有的字节数量。 --- ### 二、验证以及解决方案 针对上述可能出现状况的地方我们给出相应的检查手段与调整措施: #### 步骤一:对比源目的两端文件哈希值 利用命令生成双方文件各自的MD5其他散列算法的结果,并加以比较确定两者的一致性情况: ```bash md5sum source_file # 者 sha256sum destination_file ``` 假如两个结果一致则证明仅仅是视觉误差;如果匹配就需要继续排查其它问题所在之处。 #### 步骤二:确认是否有中途断开现象发生过 回顾一下当时运行该任务期间的日志记录信息里面有没有关于异常终止之类的提示消息。如果没有现成日志可供参考也可以尝试再次进行一次完整的测试并留意终端窗口输出的内容。 #### 步骤三:明确指定递归标志及其他参数 确保每次执行指令都准确无误地包含了必要的开关项比如“-r”代表递归处理目录结构等。同时还可以添加进度条功能方便观察整体完成度:“--progress”。 #### 示例语法如下所示: ```bash scp -rp /local/source/directory username@remotehost:/destination/path/ ``` #### 步骤四:考虑环境兼容性的调整 如果是文字型档案遇到编码困扰可先将其转码后再实施传送动作。例如借助iconv工具把UTF-8格式改成ANSI样式之后再做下一步部署安排。 --- ### 三、预防策略 为了避免将来再度碰见类似难题可以从以下方面着手改进日常运维习惯: - 定期维护更新所用软件版本保持最新状态; - 建立健壮稳定的通信链路减少意外掉线几率; - 规范化命名规则便于后续追踪定位资源位置; - 形成长效备份机制以防万一关键资料遗失无法挽回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值