1、问题背景
开发了一个文件迁移功能,将文件从机械盘迁移到固盘,提升文件读取速度。运维测试说没有效果,我花了近3个小时才定位到原因,在linux上c编程使用的rename函数,不能跨文件分区移动文件。
2、定位过程
1)让运维重复他的测试过程。看到旧的文件没有被移动,初步判断为文件移动失败。
2)查看代码。在文件移动失败时打印系统日志(rename函数调用返回非0),在系统日志找到了对应的重命名失败记录,但是没有记录下错误代码(errno)。
PS:发现没有记录errno,心里那个恨啊,差点就想再发个测试版本上去测试。笔记重点:记录错误日志给出errno,可以方便判断出错误类型。
3)难道谁改了我的代码,于是在自己的测试机上再测试了一下,一切正常呀。初步怀疑是跨磁盘移动出了问题,因为我的测试机没有ssd盘。
4)在线上机器测试,发现只要跨磁盘移动就会失败。确定为rename跨磁盘移动文件失败。
3、弄清原因
rename不支持跨文件系统移动,详解介绍(rename(2) - Linux manual page)。参考别人帖子,直接在百度使用关键字linux c rename 跨磁盘,搜索出了一篇一样的问题帖子(http://blog.51cto.com/sugarlovecxq/1681973),他的解决方案是不让文件跨磁盘。没有修改代码来解决需要跨磁盘的情况。
4、解决方案
方案一:直接使用系统调用system("mv ....");
方案二:移动文件时,判断错误代码为EXDEV时,采用copy(读文件再写文件)的方式移动文件。
可以参考nginx中的实现ngx_ext_rename_file,也可以参考linux中mv命令的实现。
5、小结
1)c语言中rename函数并不能跨文件系统移动(重命名)文件。类似的linux中的rename命令,也是不可以跨磁盘的,在编写shell脚本时需要注意。
2)遇到错误打印日志给出errno,方便排查问题;
3)测试需要使用实际的机器环境;
网友评论