在Linux里,用户层面并没有文件创建时间的概念,无论是用ls还是stat 指令,都无法获取到文件的创建时间
[tudou@tudou-pc statx]$ stat test-statx.c
文件:test-statx.c
大小:6656 块:16 IO 块:4096 普通文件
设备:805h/2053d Inode:6684737 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 1000/ tudou) Gid:( 1001/ tudou)
最近访问:2018-10-07 13:16:29.000000000 +0800
最近更改:2018-10-07 13:21:09.855461986 +0800
最近改动:2018-10-07 13:21:09.855461986 +0800
创建时间:-
可以看到「创建时间」一行总是「-」。
如果我们使用百度的话,会看到很多文章说,最近改动时间就是创建时间。的确,我们拿很多文件试验了下,这个最近改动时间(Change Time)确实和创建时间很相近,然而Change time并不是Create time,它实际是文件属性修改时间。 试一下即知:
[tudou@tudou-pc 下载]$ ./statx ~/.face
statx(/home/tudou/.face) = 0
results=fff
Size: 7589 Blocks: 16 IO Block: 4096 regular file
Device: 08:05 Inode: 5505043 Links: 1
Access: (0644/-rw-r--r--) Uid: 1000 Gid: 1001
Access: 2018-09-16 01:15:52.320014139+0800
Modify: 2018-09-16 01:15:52.320014139+0800
Change: 2018-09-16 01:15:52.320014139+0800
Birth: 2018-09-16 01:15:52.320014139+0800
Attributes: 0000000000000000 (........ ........ ........ ........ ........ ........ ....-... .---.-..)
[tudou@tudou-pc 下载]$ chattr +u ~/.face
[tudou@tudou-pc 下载]$ ./statx ~/.face
statx(/home/tudou/.face) = 0
results=fff
Size: 7589 Blocks: 16 IO Block: 4096 regular file
Device: 08:05 Inode: 5505043 Links: 1
Access: (0644/-rw-r--r--) Uid: 1000 Gid: 1001
Access: 2018-09-16 01:15:52.320014139+0800
Modify: 2018-09-16 01:15:52.320014139+0800
Change: 2018-10-07 16:17:10.929769171+0800
Birth: 2018-09-16 01:15:52.320014139+0800
Attributes: 0000000000000000 (........ ........ ........ ........ ........ ........ ....-... .---.-..)
不过,linux也不是完全不支持文件创建时间,文件系统如ext4其实是支持的,只是没有API可以获取到这个数据。比如Java提供的文件API,也就因此无法获取文件创建时间。
不过,自内核 4.11 版本引入的 statx 系统调用支持获取创建时间了,字段名里用的是 btime(Birth time)。
如果用户想要实现在代码里获取这个创建时间,那么只需要调用glibc提供的API即可。但是目前glibc还没有支持,所以只能自己用syscall函数调用。如果仅仅只是想自己实现一个小工具来获取这个时间,那么内核源码树里 samples/statx/test-statx.c 这个文件就是现成的实现。 下载源码:https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.18.12.tar.xz,选择一个和自己操作系统版本最近的源码分支 . 你要是不想下载几十M的linux源码的话,也可以从这里获取到各个linux版本的源码 编译文件:
[tudou@tudou-pc statx]$ gcc -O2 -o statx test-statx.c
In file included from /usr/include/sys/stat.h:446,
from test-statx.c:28:
/usr/include/bits/statx.h:25:8: 错误:‘struct statx_timestamp’重定义
struct statx_timestamp
^~~~~~~~~~~~~~~
In file included from test-statx.c:26:
/usr/include/linux/stat.h:56:8: 附注:原先在这里定义
struct statx_timestamp {
^~~~~~~~~~~~~~~
In file included from /usr/include/sys/stat.h:446,
from test-statx.c:28:
/usr/include/bits/statx.h:36:8: 错误:‘struct statx’重定义
注释如下两行代码:
#define _GNU_SOURCE
#define _ATFILE_SOURCE
再次编译即可。
[tudou@tudou-pc statx]$ gcc -O2 -o statx test-statx.c
[tudou@tudou-pc statx]$ ./statx test-statx.c
statx(test-statx.c) = 0
results=fff
Size: 6656 Blocks: 16 IO Block: 4096 regular file
Device: 08:05 Inode: 6684737 Links: 1
Access: (0644/-rw-r--r--) Uid: 1000 Gid: 1001
Access: 2018-10-07 13:16:29.000000000+0800
Modify: 2018-10-07 13:21:09.855461986+0800
Change: 2018-10-07 13:21:09.855461986+0800
Birth: 2018-10-07 13:16:47.771175840+0800
Attributes: 0000000000000000 (........ ........ ........ ........ ........ ........ ....-... .---.-..)
另外一个思路, 使用debugfs来搞。
附:glibc即将支持statx调用Glibc Support For Statx Is Finally Under Review
参考: https://blog.lilydjwg.me/2018/7/11/get-file-birth-time-in-linux.213101.html