Linux 的设计理念是:一切都是文件!在此简单介绍下 Linux 中常见的文件操作。
文件
通过 ls -l test
命令可以查看文件 test 的属性,通常可以得到如下的内容:
第二栏表示的是有多少文件连接到 inode ,如果是一个文件,此时这一字段表示这个文件所具有的硬链接数,如果是一个目录,则此字段表示该目录所含子目录的个数,包括 .
、..
以及隐藏目录。
每个文件都会将他的权限与属性记录到文件系统的 inode 中,不过,我们使用的目录树却是使用文件名来记录,因此每个档名就会连结到一个 i-node 这个属性记录的,就是有多少不同的档名连结到相同的一个 i-node 号码去就是了。
文件类型
在 Linux 中,总共有四种文件类型,包括普通文件、目录文件、连接文件和特殊文件,那么可以通过 file 命令来查看。
- 普通文件(regular file):包括纯文本文件 (ASCII) ,二进制文件 (binary) ,资料格式文件 (data) , data 主要是指以特定格式存储的文件,如使用 Linux 登录时会将记录存放在
/var/log/wtmp
中,这就是一个 data file,可以通过 last 来查看,但是不能用 cat 。ls -l
可以看到-
。 - 目录文件(directory):包括文件名、子目录名及其指针。
ls -l
可以看到d
。 - 连接文件(link):是指向同一索引节点的那些目录条目,通常为符号链接。
ls -l
可以看到l
。 - 设备相关文件(device):这些文件通常放在
/dev
中,又可以分为块设备文件 (如硬盘) 和字符文件 (如键盘、鼠标)。ls -l
可以分别看到b/c
。 - 网络接口文件(sockets):用于网络上的数据传输,常在
/var/run
中。ls -l
可以看到s
。 - 管道文件(FIFO, pipe):主要用于数据的读写,如命令管道。
ls -l
可以看到p
。
文件权限
其中第一位表示文件的类型;后九位中,每三位为一组,r-read/4
、w-write/2
、x-excute/1
,分别表示 拥有者、同组用户、其他人的权限。上图表示该文件为目录,拥有者有读、写、执行的权利,而用户组其他成员和其他人没有写的权利。
只有当文件所在上一级目录有 w 的权限时,才可以新建或者删除文件,对于已经存在的文件可以进行修改。
$ chown -R user:group file/dir # 修改用户和用户组,-R 表示递归
$ chmod -R 740 file/dir # 修改文件或目录的权限,-R 表示递归
$ chmod u/g/o/a +/-/= r/w/x file/dir # 分别表示user/group/others/all
文件默认属性可通过 umask
设置,umask
就是指 “Linux文件的默认属性需要减掉的权限”。
对于 Linux 来说,普通文件的最大默认属性是 666,目录的最大属性是 777;如果不想要用户在新建立文件时使用默认的属性,那么就要设置 umask 值。
在 CentOS 中,系统默认的 umask 值是 0002,那么用户在新建立普通文件时,普通文件的属性就是 666-0002=664,新建目录时,目录的属性就是 777-0002=755。
可以通过如下的命令进行查看设置。
$ umask # 查看
$ umaks 0002 # 设置
文件的特殊权限
除了上述的读写执行权限之外,Linux 还定义了其他的权限。
SUID
当一个设置了 SUID 位的可执行文件被执行时,无论那个用户来执行该文件,该文件将以所有者的身份运行,都有文件所有者的特权。如果所有者是 root 的话,那么执行人就有超级用户的特权了。
例如 /etc/passwd
的权限为 -rw-r--r-- root root
,也就是说只有 root 才能修改,但是我们可以通过 /usr/bin/passwd
来修改密码。通过 ls -l /usr/bin/passwd
可以看到其属性为 -rwsr-xr-x root root
因此在执行时获得了 root 的权限。
NOTE: 该属性仅可用在可执行文件,不用于脚本文件和目录(可以进行设置,但是应该无效)。因为脚本时一系列命令的集合体,不同的命令可能会对应于不同的属性。
SGID
当一个设置了 SGID 位的可执行文件运行时,该文件将具有所属组的特权, 任意存取整个组所能使用的系统资源。
若目录设置了 SGID ,则所有被复制到这个目录下的文件,其属组都会被重设为和这个目录一样,除非在复制文件时加上 -p
(preserve,保留文件属性) 参数,才能保留原来所属的群组设置。
NOTE: 一般来说, SGID 多用在特定的多人团队的项目开发上,在系统中用得较少。
粘着位(Sticky Bit)
只针对目录有效,对文件没有效果。如果用户在该目录下面具有 w 和 x 权限,当用户在该目录下建立文件或者目录时,只有文件拥有者和 root 用户才有权力删除(注意目录的所有者也可以删除文件的)。
设置
可以通过如下的命令进行设置。
$ chmod u+s(SUID) g+s(SGID) o+t(STICKY)
$ chmod 4755
一个文件的属性通常有 4 个八进制表示,ls 只显示了 3 个,而对于 xxx-SUID,SGID,STICKY(4,2,1)
,与 rwx
相似,也采用一个数字进行表示。
设置后,可以用 ls -l
来查看,如果本来在该位上有 x (均显示在x位上),则这些特殊标志显示为小写字母 (s, s, t)
;否则,显示为大写字母 (S, S, T)
。
对于目录来说如果通过 lsattr 无法查看属性,可以通过 ls | lsattr
查看;或者直接执行 lsattr。
文件特殊属性
文件系统中除了上述的权限配置之外,还可以通过 chattr 进行设置,使用 chattr 必须为 root 用户才可以。
chattr [-R] [-+=] [AacDdijsSu] 文件名
- A(atime):如果设置了A属性,则这个文件的最后访问时间atime不能被修改。
- a(append only):如果设置了a属性,则这个文件只能增加数据,不允许任何进程覆盖或截断这个文件。如果某个目录具有这个属性,那么只能在这个目录下建立和修改文件,而不能删除任何文件。注意,由于vi会创建一些swp文件,因此此时会出错,使用nano。
- d(No dump):在进行文件系统备份时,dump程序将忽略这个文件。
- i(immutable):如果设置了i属性,则不能对这个文件做任何修改,包括删除、修改内容等,如果要删除必须去掉该属性。如果某个目录具有这个属性,那么只能修改该目录下的文件,而不能建立和删除文件。这个是针对所有用户,而修改目录的w权限对root无效。
其中可以通过 +
添加,-
取消,以及 =
设置文件属性。
其中 e
标示文件系统支持 extents
属性,一般会在 ext4 中使用,可以通过 df -Th
lsblk -f
查看当前所挂载磁盘的文件系统类型。
所谓的 extents 属性,主要是针对大文件,只需要记录文件的起始以及结束地址即可,无需记录所有的块,可以有效降低元数据的大小。
----- 查看某个文件的磁盘分片
# filefrag -v FILENAME
文件时间属性
在 Linux 中,没有文件创建时间的概念,只有文件的访问时间、修改时间、状态改变时间,也就是说不能知道文件的创建时间。
但如果文件创建后就没有修改过,修改时间 = 创建时间;如果文件创建后,状态就没有改变过,那么状态改变时间 = 创建时间;如果文件创建后,没有被读取过,那么访问时间 = 创建时间,这个基本不太可能。
- modification time(mtime,修改时间):cp,这个时间指的是文件内容修改的时间,而不是文件属性的修改,当数据内容修改时,这个时间就会改变,用命令 ls -l 默认显示的就是这个时间。
- access time(atime,访问时间):cp, cat, more,当读取文件内容时,就会更改这个时间,例如使用 cat more vi 等命令,那么该文件的 atime 就会改变,ls stat 不会改变访问时间。注意:可能由于 Linux 缓存机制,第一次读取文件后,下次可能不会访问该文件,因此atime不会改变。
- change time(ctime,属性或位置修改时间):mv, cp, chmod, chown,当一个文件的状态改变时,这个时间就会改变,例如更改了文件的权限与属性等,它就会改变。
其它
常用命令
----- 查看文件的类型
$ file /tmp/test
----- 使用stat显示文件详细信息
$ stat file # 显示文件的信息
$ stat -t file # 与上相同,不过在一行显示,方便脚本处理
$ stat -f file # 显示文件系统的信息
----- 显示时间信息
$ ls -l --full-time file # 修改时间的完整格式,包含时区
$ ls -l --time=atime/ctime --full-time file # 显示atime/ctime