Linux 之用户、权限、存储结构与磁盘划分

Linux 在保证安全的前提下,可以让多个用户同时登陆系统工作。对于这样一个多用户多任务的系统,它是如何保证稳定与安全的呢。这一章就让我们来看看 Linux 是如何管理这些用户的吧

Linux 在保证安全的前提下,可以让多个用户同时登陆系统工作。对于这样一个多用户多任务的系统,它是如何保证稳定与安全的呢。这一章就让我们来看看 Linux 是如何管理这些用户的吧

用户与权限

Linux 中有用户与用户组的概念,

用户及用户组

用户

linux 中的用户分成 3 类:

序号 用户 UID 权限
1 系统管理员 0 管理系统的用户
2 系统用户 1 ~ 999 系统的服务程序有独立的系统用户来运行,为避免某个系统服务被黑客提权到整个服务器
3 普通用户 1000 ~ 由管理员创建的日常工作用户

用户组

用户组是为了方便对用户权限的统一管理而设置的,在 linux 中创建一个用户就会创建一个与用户同名的基本用户组,把用户加入到其他用户组时,这个其他用户组称为扩展用户组。一个用户可以有一个基本用户组和多个扩展用户组。

常用命令

序号 命令 参数 功能
1 useradd -d 指定用户的 home 目录
    -e 账户的到期时间
    -u 指定用户的 UID
    -g 指定用户的组 id
    -G 指定用户的扩展组 id
    -s 指定默认 shell
2 groupadd 组名 创建用户组
3 usermod   修改用户属性
    -c 用户备注
    -d -m 指定 home 目录并把文件移过去
    -L 锁定、禁止登陆
    -U 锁定、允许登陆
    -G 修改扩展用户组
    -g 修改基本用户组
4 passwd   修改密码、锁定密码
5 userdel   删除用户
    -r 同时删除用户及 home 目录

示例

  1. 创建一个普通用户,home 目录为 /home/wilsonuid=8888shell=/sbin/nologin
    >>> useradd -d /home/wilson -u 8888 -s /sbin/nologin wilson
    >>> id linuxprobe
    uid=8888(linuxprobe) gid=8888(linuxprobe) groups=8888(linuxprobe)
    
  2. 把 wilson 加入 root 用户组
    >>> id wilson
    uid=1000(linuxprobe) gid=1000(linuxprobe) groups=1000(linuxprobe)
    >>> usermod -G root wilson
    uid=1000(linuxprobe) gid=1000(linuxprobe) groups=1000(linuxprobe),0(root)
    
  3. 删除用户及目录
    >>> userdel -r wilson
    

文件

文件类型

linux 一切是文件,但也分成不同类型:

序号 标识 类型
1 - 普通文件
2 d 目录文件
3 l 链接文件
4 b 块设备文件
5 c 字符设备文件
6 p 管道文件

文件归属

一个文件归属包括:所有者、所有组和其他用户,

文件基本权限

基本标识

序号 标识 文件 目录
1 r 可读取内容 可读取目录中的文件列表
2 w 可增、删、改内容 可在目录中增、删、改文件名
3 x 可运行一个脚本程序 可进入目录

文件的特殊权限

权限 说明
suid 上方宝剑,临时拥有管理员权限
sgid 1. 对文件:让执行者有文件属组权限
2. 对目录:目录中创建的文件自动继承目录用户组
sbit 粘滞位/保护位,只能删除自己文件不能删除别人文件

删除文件的权限在于用户对目录文件是否有写入权限,

chmod 和 chown

命令 功能 格式
chmod 设置文件或目录的基本权限 chmod 777 abc
chown 设置文件或目录的属主和属组 chown 属主:属组 文件/目录(-R)
chown root:bin test

示例

  1. 执行者拥有属组权限
    >>> ls -l /dev/kmem
    cr--r-----   1 root system 2,  1 Feb 11 2017  kmem
    # kmem 只有 root 和 system 组可以读取
    # 用户通过 ps 命令查看 kmem 内容
    >>> -ls -l ps
    -r-xr-sr-x   1 bin system 59346 Feb 11 2017  ps
    # ps 命令具有sgid权限,用户执行ps时,会具有system组权限
    
  2. 部门内设置共享目录,员工可在目录中创建和读取文件
    >>> mkdir department
    # 让所有员工都可以读、写
    >>> chmod -Rf 777 department/
    # 增加sgid,目录中员工创建的文件自动继承目录组权限
    >>> chmod -Rf g+s department/
    # 这样普通用户在 department 中创建的文件自动继承了它的组
    
  3. 对目录设置保护位
    >>> chmod -R o+t linux/
    

文件的隐藏权限

命令

命令 格式/参数 说明
chattr chattr [参数] 文件 +参数 增加权限;-参数 删除权限
  -a 只能添加,不能删除
lsattr lsattr [参数] 文件 显示文件的隐藏属性

示例

  1. 普通用户创建目录,设置不能删除

    >>> touch test
    >>> chattr +a test
    
  2. 显示文件的隐藏属性

    [root@linuxprobe ~]# lsattr linuxprobe
    -----a---------- linuxprobe
    [root@linuxprobe ~]# chattr -a linuxprobe
    [root@linuxprobe ~]# lsattr linuxprobe
    ---------------- linuxprobe
    

文件访问控制列表 FACL

特性

  • 针对某个特定用户或者特定的用户组设置文件或目录的操作权限,就要用到文件访问控制列表(FACL)
  • 对目录设置了 FACL,则目录中的文件都继承其 FACL
  • 对文件设置 FACL,则文件不再继承目录的 FACL

命令

命令 参数 说明
setfacl setfacl [参数] 文件/目录 针对特定用户/组设置的操作权限
  -R 目录
  -m 文件
  -b 删除 FACL
getfacl getfacl 文件/目录 查看 FACL

示例

  1. 让 wilson 有查看 root 目录的权限

    >>> setfacl -Rm u:wilson:rwx /root
    >>> su - wilson
    Last login: Sat Mar 21 15:45:03 CST 2017 on pts/1
    >>> ls /root
    anaconda-ks.cfg Downloads Pictures Public
    >>> ls -ld /root
    dr-xrwx---+ 14 root root 4096 May 4 2017 /root
    # 文件权限的 . 变成了 + 说明设置了 FACL
    
  2. 查看 FACL

    >>> getfacl /root
    getfacl: Removing leading '/' from absolute path names
    # file: root
    # owner: root
    # group: root
    user::r-x
    user:wilson:rwx
    group::r-x
    mask::rwx
    other::---
    

su 命令与 sudo 服务

命令 参数 说明
su   让用户在不退出登陆的情况下,切换到其他用户
  - 完全切换,把环境变量信息也变更
sudo   提供额外的权限来完成 root 任务
  -l 列出当前用户可执行的命令
visudo   编辑 sudo 服务的配置文件

sudo 特点

  • 限制用户执行指定的命令
  • 记录用户执行的每一条命令
  • 配置文件(/etc/sudoers)提供集中的用户管理、权限与主机等参数
  • 验证密码的后 5 分钟内(默认值)无须再让用户再次验证密码

visudo

格式: 谁可以使用 允许使用的主机=(以谁的身份) 可执行命令的列表

visudo
96 ##
97 ## Allow root to run any commands anywhere
98 root ALL=(ALL) ALL
# wilson可以执行所有root命令,只需输入自己的密码
99 wilson ALL=(ALL) ALL
# 只能以root权限执行cat
100 linuxprobe ALL=(ALL) /usr/bin/cat
# 执行时不需输入密码
101 tom ALL=NOPASSWD: /usr/sbin/poweroff

存储结构

一切从 / 开始

文件系统是OS在存储设备上组织文件的方法,Linux 的文件系统把一切都看成文件来操作。所有文件都是从根目录 / 开始的,然后根据文件系统层级标准(FHS)采用树形结构组织文件。Linux 还定义了目录的用途。

注意: Linux 是区分大小写的,所以 wilso 和 Wilson 是两个不同的文件

绝对路径与相对路径

绝对路径是从 / 开始的路径,相对路径是以工作目录开始的路径

常见目录及内容

目录 功能
/boot 开机所需文件—内核、开机菜单以及所需配置文件等
/dev 以文件形式存放任何设备与接口
/etc 配置文件
/home 用户主目录
/bin 存放单用户模式下还可以操作的命令
/lib 开机时用到的函数库,以及/bin与/sbin下面的命令要调用的函数
/sbin 开机过程中需要的命令
/media 用于挂载设备文件的目录
/opt 放置第三方的软件
/root 系统管理员的家目录
/srv 一些网络服务的数据文件目录
/tmp 任何人均可使用的“共享”临时目录
/proc 虚拟文件系统,例如系统内核、进程、外部设备及网络状态等
/usr/local 用户自行安装的软件
/usr/sbin Linux系统开机时不会使用到的软件/命令/脚本
/usr/share 帮助与说明文件,也可放置共享文件
/var 主要存放经常变化的文件,如日志
/lost+found 当文件系统发生错误时,将一些丢失的文件片段存放在这里

物理设备文件

Linux 把物理设备也看成文件,这些文件的名称由内核中的udev设备管理器命名。udev服务会以守护进程的形式运行,一直监听内核的信号来管理设备 /dev 目录下的文件。

常见的硬件设备文件

硬件设备 设备文件名
IDE设备 /dev/hd[a-d]
SCSI/SATA/U盘 /dev/sd[a-p]
软驱 /dev/fd[0-1]
打印机 /dev/lp[0-15]
光驱 /dev/cdrom
鼠标 /dev/mouse
磁带机 /dev/st0或/dev/ht0

存储设备的分区

主机上的硬盘以 /dev/sd 开头,每块硬盘根据系统内核的识别顺序,用 a~p 来表示 (共16块)。硬盘的分区规则为:

  • 1~4:主分区或扩展分区
  • 5~-:逻辑分区

设备文件名的解析

我们来解析一下 /dev/sda5 这个设备文件名包含的内容:

dev

解析:

  • /dev:目录下的是硬件设备
  • sd:存储设备
  • a:同类接口中第1个被识别的设备
  • 5:这个设备是一个逻辑分区
  • /dev/sda5:系统中第一块被识别到的硬件设备中分区编号为5的逻辑分区的设备文件

主分区与逻辑分区

硬盘设备由扇区(512byte)组成。第1个扇区保存着主引导记录(446 字节)分区信息表(64字节),每一个分区信息需要16字节,所以分区信息表只能包含4个分区信息。这4个分区就是主分区。下面就是第1扇区的分布图:

mbr

为了实现更多的分区,我们就让主分区表中某个分区指向另一个分区而不再记录分区信息。这时这个分区名为扩展分区(叫分区指针更合适一点),扩展分区所指向的位置不再是一个分区,而是多个分区(即所谓的逻辑分区)的集合,而这些分区,会通过指针(下一跳的位置)的方式串联起来(实际上扩展分区项所指向的是第一个逻辑分区的首扇区,而在第一个逻辑分区的首扇区中,会记录下一个逻辑分区首扇区的地址)。要想访问到逻辑分区中的内容,需要进行多次的跳转。而要实现这一点,在启动操作系统以前是难以完成的,这也就是为什么,操作系统不能安装在逻辑分区的原因了。

扩展分区,严格地讲它不是一个实际意义的分区,它仅仅是一个指向下一个分区的指针,这种指针结构将形成一个单向链表。

文件系统

Linux 中文件建立、写入、读取、修改、转存与控制都是通过文件系统完成的。

常见的文件系统

名称 说明  
Ext3 日志文件系统,异常宕机时避免文件系统资料丢失,并能自动修复数据的不一致与错误
它会把整个磁盘的每个写入动作的细节都预先记录下来,以便在发生异常宕机后能回溯追踪到被中断的部分,然后尝试进行修复
 
Ex4 Ext3的改进版本,存储容量高达1EB,且能够有无限多的子目录  
XFS 高性能的日志文件系统,RHEL 7中默认,宕机后快速恢复被破坏的文件  

硬盘格式化

对于一块新硬盘,我们需要对它先分区,再格式化,最后挂载到文件系统中才可以使用。Linux 中有一个 super block 硬盘地图,记录整个文件系统的信息。Linux 把每个文件的权限、属性放在一个 inode 中,每个文件占有一个 128 字节的 inode。里面记录了:

  • 该文件的访问权限 (rwx)
  • 属主与属组 (owner, group)
  • 文件大小 (size)
  • 文件的时间(ctime、atime、mtime)
  • 文件的特殊权限(SUID、SGID、SBIT)
  • 文件的真实数据地址(point)

文件的实际内容则保存在block块中(大小可以是1KB、2KB或4KB),所以inode中记录着多个存放内容的block地址,当inode写满之后(一个inode的默认大小仅为128B(Ext3),记录一个block则消耗4B),又会自动分配出一个block块,专门用于像inode那样记录其他block块的信息,这样把各个block块的内容串到一起,就能够让用户读到完整的文件内容了

挂载硬件设备 mount

将设备与目录文件相关联就是挂载。命令格式为mount 文件系统 挂载目录,卸载格式为 unmount 目录

手动挂载

例如:把 /dev/sdb2 挂载到 /backup 目录,命令如下:

>>> mount /dev/sdb2 /backup

自动挂载

/etc/fstab 文件中,以格式 设备文件 挂载目录 格式类型 权限类型 是否备份 是否自检 填好后,系统启动时就会自动挂载相应设备

字段 含义
设备文件 一般为设备的路径+设备名称,也可以写唯一识别码(UUID,Universally Unique Identifier)
挂载目录 指定要挂载到的目录,需在挂载前创建好
格式类型 指定文件系统的格式,比如Ext3、Ext4、XFS、SWAP、iso9660(此为光盘设备)等
权限选项 若设置为defaults,则默认权限为:rw, suid, dev, exec, auto, nouser, async
是否备份 若为1则开机后使用dump进行磁盘备份,为0则不备份
是否自检 若为1则开机后自动进行磁盘自检,为0则不自检
示例

把文件系统为ext4的设备/dev/sdb2挂载到 /backup,默认权限,无需备份,无需自检:

>>> vim /etc/fstab

/dev/sdb2 /backup ext4 defaults 0 0

添加硬盘

把硬盘插入主板后,系统内核 udev 会检测到硬盘设备,更新 /dev 中的设备(假设为 /dev/sdb)。要读写硬盘,先要对其进行分区,我们先从中划分出2GB的分区设备,供使用:

磁盘分区 fdisk

我们用 fdisk 磁盘设备名 来对设备进行分区,它是通过交互界面完成分区的,其中参数含义如下:

参数 含义
m 查看全部可用的参数
n 添加新的分区
d 删除某个分区信息
l 列出所有可用的分区类型
t 改变某个分区的类型
p 查看分区表信息
w 保存并退出
q 不保存直接退出
  1. 执行分区命令

     >>> fdisk /dev/sdb
     Welcome to fdisk (util-linux 2.23.2).
     Command (m for help): p
     Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
     Units = sectors of 1 * 512 = 512 bytes
     ...
    
  2. 创建新分区,这里参数p是创建主分区,参数e是创建扩展分区

     Command (m for help): n
     Partition type:
     p primary (0 primary, 0 extended, 4 free)
     e extended
     Select (default p): p # 主分区
    
  3. 输入分区号(1-4)

     Partition number (1-4, default 1): 1
     # 扇区的起始位置,默认即可
     First sector (2048-41943039, default 2048):此处敲击回车
     Using default value 2048
     # 设置分区结束位置
     Last sector, +sectors or +size{K,M,G} (2048-41943039, default 41943039): +2G
     Partition 1 of type Linux and of size 2 GiB is set
    
  4. 查看分区表

     # 查看分区表
     Command (m for help): p
     Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
     Units = sectors of 1 * 512 = 512 bytes
     Sector size (logical/physical): 512 bytes / 512 bytes
     I/O size (minimum/optimal): 512 bytes / 512 bytes
     Disk label type: dos
     Disk identifier: 0x47d24a34
     Device Boot Start End Blocks Id System
     # 新建的 2G 分区 /dev/sdb1
     /dev/sdb1 2048 4196351 2097152 83 Linux
     # 输入 w 写入分区信息
     Command (m for help): w
     The partition table has been altered!
     Calling ioctl() to re-read partition table.
     Syncing disks.
    
  5. 把分区信息同步给内核

     [root@linuxprobe ]# file /dev/sdb1
     /dev/sdb1: cannot open (No such file or directory)
     [root@linuxprobe ]# partprobe
     [root@linuxprobe ]# partprobe
     [root@linuxprobe ]# file /dev/sdb1
     /dev/sdb1: block special
    

格式化 mkfs

现在得到的是一个存储设备,但没有格式化信息,Linux 不知以什么协议操作设备,所以我们还需要格式化这个硬件存储设备,使其成为一个系统操作的对象。格式化命令:mkfs <tab>

# 设备以 xfs 协议交互
[root@linuxprobe ~]# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1 isize=256 agcount=4, agsize=131072 blks
 = sectsz=512 attr=2, projid32bit=1
 = crc=0
data = bsize=4096 blocks=524288, imaxpct=25
 = sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
 = sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

挂载存储器 mount

[root@linuxprobe ~]# mkdir /newFS
# 挂载设备到文件系统
[root@linuxprobe ~]# mount /dev/sdb1 /newFS/
# 查看硬盘使用量
[root@linuxprobe ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 18G 3.5G 15G 20% /
devtmpfs 905M 0 905M 0% /dev
tmpfs 914M 140K 914M 1% /dev/shm
tmpfs 914M 8.8M 905M 1% /run
tmpfs 914M 0 914M 0% /sys/fs/cgroup
/dev/sr0 3.5G 3.5G 0 100% /media/cdrom
/dev/sda1 497M 119M 379M 24% /boot
/dev/sdb1 2.0G 33M 2.0G 2% /newFS

查看文件占用空间 du

du [选项] [文件]

>>> du -sh /newFS/
33M /newFS/

设置自动挂载

>>> vim /etc/fstab

/dev/sdb1 /newFS xfs defaults 0 0

添加交换分区

交换分区用来把内存中不常用的内容保存在硬盘里,一般交换分区大小为内存大小的 1.5~2 倍。现在我们从 /dev/sdb 中划出 5GB 分区用于交换空间。

  1. 新建分区

     >>> fdisk /dev/sdb
     Welcome to fdisk (util-linux 2.23.2).
     Changes will remain in memory only, until you decide to write them.
     ...
     # 新建分区
     Command (m for help): n
     Partition type:
     p primary (1 primary, 0 extended, 3 free)
     # 分区为主分区
     e extendedSelect (default p): p
     Partition number (2-4, default 2):
     First sector (4196352-41943039, default 4196352): 此处敲击回车
     Using default value 4196352
     # 分区大小 5G
     Last sector, +sectors or +size{K,M,G} (4196352-41943039, default 41943039): +5G
     Partition 2 of type Linux and of size 5 GiB is set
     # 显示分区信息
     Command (m for help): p
     ......
     /dev/sdb1 2048 4196351 2097152 83 Linux
     # 新建的分区 
     /dev/sdb2 4196352 14682111 5242880 83 Linux
     # 写入分区表
     Command (m for help): w
     The partition table has been altered!
    
  2. 分区格式化为 SWAP

     >>> mkswap /dev/sdb2
     Setting up swapspace version 1, size = 5242876 KiB
     no label, UUID=2972f9cb-17f0-4113-84c6-c64b97c40c75
    
  3. SWAP 挂载到文件系统

     # 查看分区大小
     [root@linuxprobe ~]# free -m
     total used free shared buffers cached
     Mem: 1483 782 701 9 0 254
     -/+ buffers/cache: 526 957
     Swap: 2047 0 2047
     # 用 swapon 命令挂载
     [root@linuxprobe ~]# swapon /dev/sdb2
     # 交换分区变大了
     [root@linuxprobe ~]# free -m
     total used free shared buffers cached
     Mem: 1483 785 697 9 0 254
     -/+ buffers/cache: 530 953
     Swap: 7167 0 7167
    
  4. 设置自动挂载交换分区

     >>> vim /etc/fstab
    
     /dev/sdb2/ swap swap defaults 0 0 
    

磁盘配额 quota

管理员需要针对用户和用户组,分配特定文件夹可以使用的最大空间和最大文件数量,命令为 quota。限制分为软限制和硬限制,软限制只会给出警告。

我们设置 /boot 目录让它支持 quota 磁盘配额技术:

  1. quota 支持

     >>> vim /etc/fstab
        
     /dev/mapper/rhel-root / xfs defaults 1 1
     # 让 boot 支持配额
     UUID=812b1f7c-8b5b-43da-8c06-b9999e0fe48b /boot xfs defaults,uquota 1 2
     >>> reboot
        
     >>> mount | grep boot
     # boot 已支持配额
     /dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,usrquota)
    
  2. 创建一个对 /boot 有写入权限的用户 tom

     >>> useradd tom
     >>> chmod -Rf o+w /boot
    
  3. 设计配额服务

     # 硬盘使用量的软限制和硬限制分别为3MB和6MB
     # 创建文件数量的软限制和硬限制分别为3个和6个
     >>>  xfs_quota -x -c 'limit bsoft=3m bhard=6m isoft=3 ihard=6 tom' /boot
     >>> xfs_quota -x -c report /boot
     User quota on /boot (/dev/sda1)   Blocks
     User ID Used Soft Hard Warn/Grace
     ---------- --------------------------------------------------
     root 95084 0 0 00 [--------]
     # tom 用户
     tom 0 3072 6144 00 [--------]
    
    • -c:以参数的形式设置要执行的命令
    • -x:专家模式,让运维人员能够对quota服务进行更多复杂的配置
  4. 用 tom 用户,创建体积为 5MB 和 8MB 文件

     >>> su - tom
     # 写入成功
     >>> dd if=/dev/zero of=/boot/tom bs=5M count=1
     5242880 bytes (5.2 MB) copied, 0.123966 s, 42.3 MB/s
     # 写入失败
     >>> dd if=/dev/zero of=/boot/tom bs=8M count=1
     dd: error writing ‘/boot/tom’: Disk quota exceeded
    
  5. 重新编辑用户配额

    edquota [参数] [用户] 用户编辑配额。

     >>> edquota -u tom
    

    -u:针对哪个用户进行设置 -g:针对哪个用户组进行设置

软链接和硬链接

  • 硬链接 指向原始文件 inode 的指针,系统不为它分配独立的 inode,所以硬链接文件和原始文件其实就是同一个文件,只是名称不同。

    每添加一个硬链接,该文件的 inode 连接数加1;只有当文件的连接数为0时,它才算彻底删除

    所以即使原文件被删除,我们还是可以通过硬链接来访问文件。

  • 软链接 仅包含所链接的文件路径,类似“快捷方式”

链接命令 ln

ln [选项] 链接 原文件 其中 -s 创建符号链接,否则创建硬链接

参数 功能
-s 创建“符号链接”(如果不带-s参数,则默认创建硬链接)
-f 强制创建文件或目录的链接
-i 覆盖前先询问
-v 显示创建链接的过程

区别:

  • 软链接:快捷方式
  • 硬链接:新建了一个inode(block 指针),不能对目录操作,不能跨分区

增加硬链接,原文件链接数增加到了 2

>>> ln readme.txt readit.txt
>>> ls readme.txt
# 链接数为 2
-rw-r--r-- 2 root root 26 Jan 11 00:13 readme.txt