3.Linux文件系统和目录管理

3.Linux文件系统和目录管理

3.1. Linux目录结构与文件类型

3.1.1 Linux目录结构

  • 根目录结构

    bin   dev  home  lib64       media  opt   root  sbin  sys  usr
    boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var
    
  • 根目录说明

    /boot:存放启动引导文件,如内核文件vmlinuz、启动引导程序/boot/grub2和bootloader
    /dev:存放设备文件及特殊文件,如/dev/null、/dev/zero、/dev/loop*、/dev/sd*
    /etc:存放配置文件
    /mnt:临时设备挂载点
    /opt:第三方软件安装目录
    /proc:虚拟文件系统,存放位于内存中的数据,如系统内核、进程、网络状态、外接设备状态
    /srv:运行中的网络服务需要的数据,存放在该目录中
    /sys:虚拟文件系统,存放位于内存中的数据,如内核、文件系统信息(硬件设备)
    /var:存放缓存和日志的目录,如/var/log、/var/cache
    
  • /usr目录结构

    bin  etc   include  lib  lib64   local  sbin  share  src  tmp
    
  • /usr目录说明

    /usr/bin、/usr/sbin:用户可执行命令的存放目录(普通用户、root用户)
    /usr/lib、/usr/lib64:系统函数库存放目录(32位、64位)
    /usr/include:C/C++的头文件存放目录
    /usr/share:主要是只读文件和共享文件,如帮助文档man、软件说明文档doc
    /usr/src:源代码存放目录
    /usr/local:第三方软件安装目录
    
  • centos7之后的链接文件

    lrwxrwxrwx.  1 root root     7 Jul  8 01:12 bin -> usr/bin
    lrwxrwxrwx.  1 root root     7 Jul  8 01:12 lib -> usr/lib
    lrwxrwxrwx.  1 root root     9 Jul  8 01:12 lib64 -> usr/lib64
    lrwxrwxrwx.  1 root root     8 Jul  8 01:12 sbin -> usr/sbin
    

3.1.2 Linux文件类型

  • 普通文件、目录、链接文件

    # - 普通文件
    $ ll /etc/passwd
    -rw-r--r--. 1 root root 798 Jul  8 01:20 /etc/passwd
    
    # d 目录文件
    $ ll -d /home
    drwxr-xr-x. 3 root root 4096 Nov  5  2016 /home
    
    # l 链接文件
    $ ll -d /usr/tmp
    lrwxrwxrwx. 1 root root 10 Jul  8 01:12 /usr/tmp -> ../var/tmp
    
  • 其他文件

    # b 块设备
    $ ll /dev/sda
    brw-rw---- 1 root disk 8, 0 Jul 10 10:12 /dev/sda
    
    # c 字符设备
    $ ll /dev/zero
    crw-rw-rw- 1 root root 1, 5 Jul 10 10:12 /dev/zero
    
    # p 管道文件
    
    # s 套接字文件
    
    

3.2 Linux文件与目录常用指令

3.2.1 查看与切换路径

  • pwd 查看当前路径

    # 查看当前路径
    [demo@localhost network-scripts]$ pwd
    /etc/sysconfig/network-scripts
    
    # 查看文件的 dirname
    [demo@localhost network-scripts]$ dirname /etc/sysconfig/network-scripts/ifcfg-enp0s8
    /etc/sysconfig/network-scripts
    
    # 查看文件的 basename
    [demo@localhost network-scripts]$ basename /etc/sysconfig/network-scripts/ifcfg-enp0s8
    ifcfg-enp0s8
    
  • cd DIR 切换路径

    # 切换到家目录
    [demo@localhost network-scripts]$ cd
    
    # 切换到之前所在路径
    [demo@localhost ~]$ cd -
    /etc/sysconfig/network-scripts
    # - 所表示的路径是存放在OLDPWD变量中的
    [demo@localhost network-scripts]$ echo $OLDPWD
    /home/demo
    

3.2.2 查看文件或目录 ls

  • 命令格式

    # 支持多个参数,多个文件
    ls [OPTION]... [FILE]...
    
  • 常用

    # -1  每行仅打印一列
    $ ls -1 /home/demo
    a.txt
    a.zip
    b.txt
    
    
    # -a  显示隐藏目录
    [demo@localhost network-scripts]$ ls -a /home/demo
    .  ..  a.txt  a.zip  .bash_history  .bash_logout  .bash_profile  .bashrc  b.txt 
    
    # -l  显示详细信息
    [demo@localhost network-scripts]$ ll /home/demo
    -rwxrwxrwx 1 demo demogroup    0 Jul 11 22:56 a.txt
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:57 a.zip
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:56 b.txt
    
    # -d  列举目录本身,而不是目录下的文件
    [demo@localhost network-scripts]$ ll -d /home/demo
    drwx------ 3 demo demogroup 4096 Jul 11 23:00 /home/demo
    
  • 排序

    # -S 按照文件大小排序
    [demo@localhost network-scripts]$ ll -S
    -rw-r--r--. 1 root root 31027 May  3  2017 network-functions-ipv6
    -rw-r--r--. 1 root root 18919 May  3  2017 network-functions
    
    # -r 倒序
    [demo@localhost network-scripts]$ ll -S -r
    -rw-r--r--. 1 root root 18919 May  3  2017 network-functions
    -rw-r--r--. 1 root root 31027 May  3  2017 network-functions-ipv6
    
    # -t 按照时间排序
    [demo@localhost network-scripts]$ ll -t
    -rw-r--r--  1 root root   327 Jul  9 12:24 ifcfg-enp0s8
    -rw-r--r--. 1 root root   282 Jul  8 09:35 ifcfg-enp0s3
    
    # -r 倒序
    [demo@localhost network-scripts]$ ll -rt
    -rw-r--r--. 1 root root   282 Jul  8 09:35 ifcfg-enp0s3
    -rw-r--r--  1 root root   327 Jul  9 12:24 ifcfg-enp0s8
    
  • 类型

    # -X 按照后缀类型排序
    [demo@localhost ~]$ ll -X /home/demo
    drwxr-xr-x 2 demo demogroup 4096 Jul 11 22:56 tmp
    -rwxrwxrwx 1 demo demogroup    0 Jul 11 22:56 a.txt
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:56 b.txt
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:57 a.zip
    
    # -F 按照文件类型添加后缀
    [demo@localhost ~]$ ll -F /home/demo
    -rwxrwxrwx 1 demo demogroup    0 Jul 11 22:56 a.txt*
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:57 a.zip
    -rw-r--r-- 1 demo demogroup    0 Jul 11 22:56 b.txt
    drwxr-xr-x 2 demo demogroup 4096 Jul 11 22:56 tmp/
    

3.2.3 Linux文件信息

  • linux文件元数据信息

    linux文件可分为两部分,属性信息(元数据,meta data)和文本内容(data),用stat FILENAME 查看

    # 查看文件元数据
    $ stat ifcfg-enp0s8
      File: ‘ifcfg-enp0s8’
      Size: 327        Blocks: 8          IO Block: 4096   regular file
    Device: fd00h/64768d Inode: 397582      Links: 1
    Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
    Access: 2023-07-12 00:31:46.378000000 +0800
    Modify: 2023-07-09 12:24:48.229000000 +0800
    Change: 2023-07-09 12:24:48.234000000 +0800
    Birth: -
    
    # 说明:
    atime:access time,访问时间
    mtime:modify time,修改时间
    ctime:change time,元数据修改时间
    
  • 文件类型

    # 文本类型
    [demo@localhost network-scripts]$ file ifcfg-enp0s8
    ifcfg-enp0s8: ASCII text
    
    # 文件夹
    [demo@localhost ~]$ file /home/demo
    /home/demo: directory
    
    # 链接文件
    [demo@localhost bin]$ file /bin
    /bin: symbolic link to 'usr/bin'
    
    # 块设备
    [demo@localhost ~]$ file /dev/sda
    /dev/sda: block special
    

3.2.4 文件通配符

  • 通配符是指采用特定的符号(元字符)来匹配特定的含义,用于过滤

    # * 表示任意个所有字符
    [demo@localhost ~]$ ls *.txt
    aa.txt  a.txt  bb.txt  b.txt  c.txt
    
    # ? 表示任意单个字符
    [demo@localhost ~]$ ls ?.txt
    a.txt  b.txt  c.txt
    
    # [] 表示列举出的任意一个字符
    [demo@localhost ~]$ ls [ac].txt
    a.txt  c.txt
    
    # [m-n] 表示给定范围的内的任意一个字符
    [demo@localhost ~]$ ls [a-c].txt
    a.txt  b.txt  c.txt
    
    # [^] 表示排除列举出字符的任意一个字符
    [demo@localhost ~]$ ls [^ac].txt
    b.txt
    
    [demo@localhost ~]$ ls [^ac][a-c].txt
    bb.txt
    

3.2.5 创建空文件与刷新时间

  • 命令格式

    touch [OPTION]... FILE...
    
    # [OPTION]
      -a                     change only the access time
      -c, --no-create        do not create any files
      -m                     change only the modification time
    
  • touch FILENAME:创建空文件 或 刷新时间

    # 查看文件
    [demo@localhost tmp]$ ll
    -rw-r--r-- 1 demo demogroup 65 Jul 12 23:30 exist.txt
    
    # 当文件不存在时,创建空文件
    [demo@localhost tmp]$ touch demo.txt
    [demo@localhost tmp]$ ll
    -rw-r--r-- 1 demo demogroup  0 Jul 12 23:49 demo.txt
    -rw-r--r-- 1 demo demogroup 65 Jul 12 23:30 exist.txt
    
    # 当文件存在时,刷新文件时间,不改变文件内容(大小65未改变)
    [demo@localhost tmp]$ touch exist.txt 
    [demo@localhost tmp]$ ll
    -rw-r--r-- 1 demo demogroup  0 Jul 12 23:49 demo.txt
    -rw-r--r-- 1 demo demogroup 65 Jul 12 23:57 exist.txt
    
    # 说明:touch FILE 创建文件比 > FILE更安全,当FILE存在时,不会改变文件内容
    
  • touch常配合date生成日期空文件

    # 生成当天文件
    $ touch demo_`date +'%F'`.txt
    
    # 生成去年今天文件
    $ touch $(date -d "-1 year" +%F_%T).log
    
    # 结果
    $ ls
    2022-07-13_00:05:17.log  
    demo_2023-07-13.txt
    

3.2.6 复制文件和目录

  • cp:命令格式

    Usage: cp [OPTION]... [-T] SOURCE DEST
            # 复制文件FILE,并重命名为DESTFILE
            cp FILE DESTFILE
            # 复制文件夹DIR,并重命名为DESTDIR,复制时需要加上-r递归选项
            cp -r /DIR /DEST/DESTDIR
    
      or:  cp [OPTION]... SOURCE... DIRECTORY
            # 复制文件FILE FILE2 到指定目录DIR下
            cp FILE FILE2 /DIR/
            # 复制目录下的所有文件,到指定目录DIR下,复制时需要加上-r递归选项
            cp -r /OLD/* /DIR/
    
      or:  cp [OPTION]... -t DIRECTORY SOURCE...
            # 基本不用
    
  • -a:保留元数据信息复制,等同于-dR --preserve=all

    -rw-r--r-- 1 demo demogroup 0 Jul 14 01:45 source
    
    # 默认复制会更改文件元数据信息
    $ cp source dest
    -rw-r--r-- 1 demo demogroup 0 Jul 14 01:45 source
    -rw-r--r-- 1 root root      0 Jul 14 01:46 dest
    
    # -a 保留元数据信息复制(-a 等同于 -dR --preserve=all)
    $ cp -a source target
    -rw-r--r-- 1 demo demogroup 0 Jul 14 01:45 source
    -rw-r--r-- 1 demo demogroup 0 Jul 14 01:45 target
    
  • -v:显示执行过程

    # -v 显示具体执行过程,多用于批量移动时
    [demo@localhost ~]$ cp -v DIR/* DEST/
    ‘DIR/a.txt’ -> ‘DEST/a.txt’
    ‘DIR/b.txt’ -> ‘DEST/b.txt’
    
    # -av 常用组合,保留所有元数据属性,批量显示执行过程复制
    $ cp -av DIR/* DEST/
    
  • -d:保留链接属性

    # 源文件
    $ ll  /etc/grub2.cfg
    lrwxrwxrwx. 1 root root 22 Jul  8 01:15 /etc/grub2.cfg -> ../boot/grub2/grub.cfg
    $ ll /boot/grub2/grub.cfg
    -rw-r--r--. 1 root root 4255 Jul  8 01:20 /boot/grub2/grub.cfg
    
    # -d 保留链接属性
    $ cp -d /etc/grub2.cfg ./grub2.cfg
    # 不加该参数时会把链接文件所指向的目标文件复制一份
    $ cp /etc/grub2.cfg ./grub1.cfg
    
    # 复制结果
    -rw-r--r-- 1 root root      4255 Jul 14 01:55 grub1.cfg
    lrwxrwxrwx 1 root root 22 Jul 14 01:55 grub2.cfg -> ../boot/grub2/grub.cfg
    
  • -r-R:递归复制

    [root@localhost demo]# ls
    DIR
    
    # 不加参数,复制文件夹不成功
    [root@localhost demo]# cp ./DIR ./
    [root@localhost demo]# cp ./DIR ./NEW-DIR
    cp: omitting directory ‘DIR’
    
    # -r 递归复制文件夹及其子文件,并重新命名
    [root@localhost demo]# cp -r ./DIR ./NEW-DIR
    
    # -r 递归复制文件夹及其子文件,到指定目录下(注意结尾有/)
    [root@localhost demo]# cp -r ./DIR ./NEW-DIR/
    [root@localhost demo]# ls
    DIR  NEW-DIR
    
    # -r 递归复制文件夹下的所以文件到指定目录
    [root@localhost demo]# cp -r ./DIR/* ./NEW-DIR/
    
  • 其他选项

    -i   覆盖前提示,cnetos中cp定义了别名(alias cp='cp -i'),默认就有该参数
    -b   目标文件存在时,备份后进行覆盖
    -u   保留最新版本覆盖,复制时如果目标文件存在且版本较新不覆盖,否则覆盖
    
  • 用法举例

    $ echo hello{,.zip}
    hello hello.zip
    
    # 备份时常用-a选项
    $ cp -a source{,.bak}
    
    # 每天生成日志
    $ cp -a source{,.`date +%F`.log}
    
    # 显示结果
    source  source.bak  source.2023-07-14.log
    

3.2.7 移动和重命名文件

  • mv:命令格式

    mv [OPTION]... [-T] SOURCE DEST
        # 重命名文件:将FILE重命名为DESTFILE
        mv FILE DESTFILE
        # 重命名文件夹:将DIR移动到DEST目录下并重命名为DESTDIR  
        mv DIR/ DEST/DESTDIR
    
    mv [OPTION]... SOURCE... DIRECTORY
        # 移动文件FILE FILE2 到指定目录DIR下
        mv FILE FILE2 /DIR/
        # 移动目录下的所有文件,到指定目录DIR下
        mv  /OLD/* /DIR/
    
    mv [OPTION]... -t DIRECTORY SOURCE...
        # 基本不用
    
  • rename:命令格式

    rename [options] expression replacement file...
        # 将所有 TXT 后缀文件改为 LOG 后缀
        rename -v .TXT .LOG /home/demo/*.TXT
    
  • mvrename的区别

    # -v 显示具体执行过程,两个都有该参数
    
    # mv 移动(支持批量),重命名(不支持批量)
    # rename 重命名(支持批量),但不能移动
    
    
    # 批量移动 mv ,将DIR下的所有文件移动到DEST目录下
    [demo@localhost ~]$ mv -v DIR/* DEST/
    ‘DIR/a.TXT’ -> ‘DEST/a.TXT’
    ‘DIR/b.TXT’ -> ‘DEST/b.TXT’
    
    # 批量重命名 rename ,将所有 TXT 后缀文件改为 LOG 后缀
    [demo@localhost ~]$ rename -v .TXT .LOG DEST/*.TXT
    `DEST/a.TXT' -> `DEST/a.LOG'
    `DEST/b.TXT' -> `DEST/b.LOG'
    

3.2.8 删除文件

  • rm:命令格式

    rm [OPTION]... FILE...
    # 删除FILE2 和 FILE3
    rm -i FILE2 FILE3
    
  • -i:每次删除前提示

    # -i 选项最好设为别名,每次删除前都提示
    alias rm='rm -i'
    
    # 删除FILE开头,且每次删除前提示
    rm -i FILE*
    
  • -f:删除前不提示(忽略不存在的文件和参数,从不提示)

  • -r:递归删除目录及其子文件

    # -f 不能删除目录
    [demo@localhost ~]$ rm -f filedir/
    rm: cannot remove ‘filedir/’: Is a directory
    
    # -r 删除目录及其子文件,配合-i更安全,但是麻烦
    [demo@localhost ~]$ rm -ir filedir/
    rm: descend into directory ‘filedir/’? y
    rm: remove regular empty file ‘filedir/c.txt’? n
    rm: remove regular empty file ‘filedir/a.txt’? n
    rm: remove regular empty file ‘filedir/b.txt’? n
    rm: remove directory ‘filedir/’? n
    
    # -rf 危险操作,不提示 递归删除
    
  • 含有特殊字符的文件删除

    # 创建含有特殊字符文件
    [demo@localhost ~]$ touch ./-foo
    [demo@localhost ~]$ touch -- -foo2
    -foo -foo2
    
    # 错误的删除
    rm -foo
    rm -foo2
    
    # 正确的删除,通过加路径的方式 或 通过--方式
    rm ./-foo 
    rm -- -foo2
    
  • 大文件删除方式一(建议)

    # 模拟大文件:通过cp持续往文件中写入/dev/zero,假设结果文件bigfile.img为1G
    cp /dev/zero /boot/bigfile.img
    # 模拟大文件被占用:其他用户通过vim打开bigfile.img且尚未关闭
    vim /boot/bigfile.img
    
    # 通过cat将/dev/null替换写入大文件(注意不是追加),达到清空该大文件的效果
    cat /dev/null > /boot/bigfile.img
    
    # 然后再删除该大文件
    rm /boot/bigfile.img
    
    # 此时空间被释放
    
  • 大文件删除方式二(建议使用方式一)

    # 模拟大文件:通过cp持续往文件中写入/dev/zero,假设结果文件bigfile.img为1G
    cp /dev/zero /boot/bigfile.img
    # 模拟大文件被占用:其他用户通过vim打开bigfile.img且尚未关闭
    vim /boot/bigfile.img
    
    # 先使用rm删除,此时存储空间并不会释放,但文件已经不存在了
    rm /boot/bigfile.img
    
    # 通过lsof命令找到被删除的文件
    lsof | grep deleted 
    lsof | grep 'bigfile.img'
    # 配合w查看那个用户在执行什么进程
    w | grep 'vim /boot/bigfile.img'
    
    # 查看占用该文件的进程(假设进程号为1888),是服务看能否重启,普通进程看能否杀掉
    kill -9 1888
    
    # 此时空间被释放
    

3.2.9 目录的创建和删除

  • mkdir:命令格式

    mkdir [OPTION]... DIRECTORY...
        # 创建文件夹
        mkdir DIR1 DIR2
    
        # -v 创建文件夹的时候显示执行过程
        # -p 递归创建目标文件夹 及其 父目录(不存在时)
        mkdir -pv DIR/PARENT/DESTDIR
    
        # -m 创建时直接指定权限
    
        # 批量创建
        mkdir /data/mysql/{data,log,etc}
    
  • tree:显示文件及文件夹

    # tree 非自带默认软件,有时需要手动安装
    
    # 显示目录下的所有文件及其文件夹
    tree /home/demo
    
    # -d 仅显示指定目录下的文件夹
    tree -d /home/demo
    
  • rmdir:删除空文件夹

    # rmdir 只能删除空目录
    rmdir emptyDIR
    
    
    [demo@localhost ~]$ mkdir -pv a/b/c
    mkdir: created directory ‘a’
    mkdir: created directory ‘a/b’
    mkdir: created directory ‘a/b/c’
    
    # -p 递归删除空目录(先删除最内层,依次往外删除),遇到非空时终止
    [demo@localhost ~]$ rmdir -pv a/b/c
    rmdir: removing directory, ‘a/b/c’
    rmdir: removing directory, ‘a/b’
    rmdir: removing directory, ‘a’
    
    # 若b目录下存在b.txt则会删除失败终止,不再往外侧删除u
    rmdir: removing directory, ‘a/b’
    rmdir: failed to remove directory ‘a/b’: Directory not empty
    

3.3. Linux索引节点和链接

3.3.1 Linux索引节点

  • 什么是inode

    Linux中的文件分为数据部分和元信息部分,其中储存文件元信息部分的区域就叫做索引节点(inode)

    储存数据部分的区域叫做数据块(block),每个块大小为4K,由8个连续的扇区组成,而扇区(Sector)是存储文件的最小单位,每个扇区大小为512字节

  • inode的内容

    # 可以通过stat命令查看文件的inode内容,即元数据信息
    $ stat FILENAME
    
    inode由以下部分组成
      文件大小  
      文件类型
      inode节点号
      链接数 
      文件权限 
      文件属主  
      文件属组  
      文件时间: Access Modify Change  
      文件数据块位置 
    
  • inode节点号

    linux中每个分区管理各自的节点编号,各个分区互不影响。同一分区中节点编号相同,则必然指向同一数据块

    # 查看各个分区的节点编号使用情况
    [demo@localhost ~]$ df -i
    Filesystem              Inodes IUsed  IFree IUse% Mounted on
    /dev/mapper/centos-root 655360 30150 625210    5% /
    /dev/sda1                76912   335  76577    1% /boot
    /dev/mapper/centos-home 504928    26 504902    1% /home
    
    # 查看具体文件的节点号
    [demo@localhost ~]$ ll -i file.txt 
    260623 -rw-r--r-- 1 demo demogroup 21 Jul 18 23:36 file.txt
    
    # 查看具体文件的节点号
    [demo@localhost ~]$ stat file.txt 
    File: ‘file.txt’
    Size: 21         Blocks: 8          IO Block: 4096   regular file
    Device: fd02h/64770d Inode: 260623      Links: 1
    Access: (0644/-rw-r--r--)  Uid: ( 1001/    demo)   Gid: ( 1001/demogroup)
    Access: 2023-07-18 23:36:17.725000000 +0800
    Modify: 2023-07-18 23:36:17.725000000 +0800
    Change: 2023-07-18 23:36:17.725000000 +0800
    Birth: -
    
  • 磁盘空间问题

    # 新建文件时,提示磁盘空间不足,No space left on device
    
    # 排查磁盘存储空间是否已满
    $ df -h
    
    # 排除inode节点编号是否已用完
    $ df -i
    

3.3.2 硬链接

  • 文件访问的过程

    Linux中以节点号来区分文件,用户通过文件名访问文件时,Linux操作系统会根据文件名获取节点编号,再由inode找到其对应的数据块,从而访问文件内容。
    文件名称只是便于用户访问文件的途径,节点编号才是文件的唯一标识。

  • 硬链接的含义

    硬链接的本质就是同一个inode编号(同一个文件)拥有不同的文件名,文件名的个数就是该文件的链接数

  • 硬链接的创建

    # 命令格式
    ln TARGET LINK_NAME
    
    # TARGET文件指向inode编号为260623的数据块,此时链接数为1
    $ ll -i /home/demo/TARGET 
    260623 -rw-r--r-- 1 demo demogroup 21 Jul 18 23:36 TARGET
    
    # 创建硬链接文件
    $ ln /home/demo/TARGET /home/demo/hardlink/LINK_NAME
    
    # LINK_NAME文件也指向inode编号为260623的数据块,此次链接数为2
    $ ll -i /home/demo/TARGET hardlink/LINK_NAME 
    260623 -rw-r--r-- 2 demo demogroup 21 Jul 18 23:36 hardlink/LINK_NAME
    260623 -rw-r--r-- 2 demo demogroup 21 Jul 18 23:36 TARGET
    # 文件大小,权限,内容都一样,就是同一份文件,无论使用哪个文件名去修改该数据块,另一个文件名查看也随之发生改变
    
    # 删除文件,无论是TARGET还是LINK_NAME都会导致链接数减少,但是相互之间不影响,删除一个通过另一个文件名仍可以访问该数据块。(都删了呢)
    $ rm /home/demo/TARGET
    $ rm /home/demo/hardlink/LINK_NAME
    
  • 硬连接的局限性

    # 不能跨分区创建硬链接,因为硬连接本质是指向同一inode编号的数据块,而inode是以分区管理的(/和/home不在一个分区)
    [demo@localhost ~]$ ln /home/demo/TARGET /LINK_NAME
    ln: failed to create hard link ‘/LINK_NAME’ => ‘/home/demo/TARGET’: Invalid cross-device link
    
    # 不能为文件夹创建硬链接
    [demo@localhost ~]$ ln /home/demo/hardlink /home/link
    ln: ‘/home/demo/hardlink’: hard link not allowed for directory
    

3.3.3 软链接

  • 软链接的含义

    软链接是指向源文件的链接类型文件,与源文件是两个不同的文件(inode编号与源文件不同),需要通过源文件才能访问数据块

  • 软链接的命令格式

    # 命令格式
    $ ln -s TARGET LINK_NAME
    $ ln -s SOURCE_DIR LINK_DIR
    
    # 软链接支持跨分区创建,(/和/home不在一个分区)
    ln -s /home/demo/TARGET /LINK_NAME
    
    # 支持为文件夹创建软链接
    ln -s /home/demo/source_dir /linkdir
    
  • 软链接的创建

    # TARGET的inode编号:260623,链接数为1
    $ ll -i /home/demo/TARGET 
    260623 -rw-r--r-- 1 demo demogroup 21 Jul 18 23:36 TARGET
    
    # 创建软链接文件
    [demo@localhost ~]$ ln -s /home/demo/TARGET /home/demo/softlink/LINK_NAME
    
    # LINK_NAME的inode编号:260624,链接数为1,文件类型为链接文件
    [demo@localhost ~]$ ll -i /home/demo/TARGET /home/demo/softlink/LINK_NAME
    260624 lrwxrwxrwx 1 demo demogroup 17 Jul 19 23:02 /home/demo/softlink/LINK_NAME -> /home/demo/TARGET
    260623 -rw-r--r-- 1 demo demogroup 21 Jul 18 23:36 /home/demo/TARGET
    
    # 链接文件需要通过源文件才能访问,当源文件删除时,链接文件存在但是不能访问
    [demo@localhost ~]$ rm /home/demo/TARGET
    [demo@localhost ~]$ ll -i /home/demo/TARGET /home/demo/softlink/LINK_NAME
    260624 lrwxrwxrwx 1 demo demogroup 17 Jul 19 23:02 /home/demo/softlink/LINK_NAME -> /home/demo/TARGET
    [demo@localhost ~]$ cat /home/demo/softlink/LINK_NAME
    cat: /home/demo/softlink/LINK_NAME: No such file or directory
    
  • 软链接的适用场景

    # 模拟应用不同版本
    [demo@localhost ~]$ mkdir app-v{1..3}.0
    
    # 创建1.0版本的软链接(不建议使用相对路径)
    [demo@localhost ~]$ ln -s app-v1.0 app
    lrwxrwxrwx 1 demo demogroup    8 Jul 19 23:20 app -> app-v1.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v1.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v2.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v3.0
    
    # 改为3.0版本的软链接,创建软链接建议使用绝对路径
    [demo@localhost ~]$ rm app
    [demo@localhost ~]$ ln -s /home/demo/app-v3.0 /home/demo/app
    lrwxrwxrwx 1 demo demogroup   19 Jul 19 23:20 app -> /home/demo/app-v3.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v1.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v2.0
    drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 app-v3.0
    
    [demo@localhost ~]$ ll -id /home/demo/app-v3.0 /home/demo/app
    260617 lrwxrwxrwx 1 demo demogroup   19 Jul 19 23:20 /home/demo/app -> /home/demo/app-v3.0
    260616 drwxr-xr-x 2 demo demogroup 4096 Jul 19 23:18 /home/demo/app-v3.0
    

3.4. 标准I/O重定向和管道

3.4.1 文件描述符与标准I/O

  • 文件描述符

    Linux系统中一切皆为文件,这其中就包括键盘、显示器这些设备文件。为了表示已经打开的文件,Linux会为每个文件分配一个编号(从0开始),这个编号就被称为文件描述符(File Descriptor)
    可参考该链接Linux文件描述符到底是什么进行深入了解

  • 标准I/O

    Linux中会为每个进程默认打开3个文件(占用3个文件描述符),分别对应0:STDIN 标准输入1:STDOUT 标准输出2:STDERR 标准错误

    # 标准I/O及其对应的文件描述符
    [demo@localhost ~]$ ll /dev/std*
    lrwxrwxrwx 1 root root 15 Jul 20 22:56 /dev/stderr -> /proc/self/fd/2
    lrwxrwxrwx 1 root root 15 Jul 20 22:56 /dev/stdin -> /proc/self/fd/0
    lrwxrwxrwx 1 root root 15 Jul 20 22:56 /dev/stdout -> /proc/self/fd/1
    
    # 查看文件描述符所属进程
    [demo@localhost ~]$ ll /proc/self/fd/[0-2]
    lrwx------ 1 demo demogroup 64 Jul 20 22:58 /proc/self/fd/0 -> /dev/pts/0
    lrwx------ 1 demo demogroup 64 Jul 20 22:58 /proc/self/fd/1 -> /dev/pts/0
    lrwx------ 1 demo demogroup 64 Jul 20 22:58 /proc/self/fd/2 -> /dev/pts/0
    
    # pts/0就是当前登录终端
    [demo@localhost ~]$ tty
    /dev/pts/0
    

3.4.2 I/O重定向

  • I/O重定向的含义

    stdin默认接收当前终端的输入,stdout与stderr默认输出到当前终端,
    重定向就是读取其他设备/文件的输入、输出到其他设备/文件(不使用当前终端的默认的输入输出)。
    包括stdin重定向stdout重定向stderr重定向

  • stdout/stderr重定向到不同文件

    #  >  stdout(输出)重定向
    $ tty > tty.out
    [demo@localhost ~]$ cat tty.out 
    /dev/pts/0
    
    # 1>  stdout(输出)重定向
    $ hostname 1> hostname.out
    [demo@localhost ~]$ cat tty.out
    localhost.localdomain
    
    # 2> stderr(错误)重定向
    $ rmdir tty.out 2> rmdir.err
    [demo@localhost ~]$ cat rmdir.err 
    rmdir: failed to remove ‘tty.out’: Not a directory
    
    # 输出和错误重定向不同文件
    $ ls /home/out /home/err > out.txt 2> err.txt
    
  • stdout/stderr重定向到同一文件

    # 推荐使用
    $ ls /home/out /home/err &> /home/all.log 
    
    $ ls /home/out /home/err > /home/all.log 2>&1
    
    $ ls /home/out /home/err 2> /home/all.log 1>&2
    
    
  • 重定向的覆盖和追加

    # > 是覆盖重定向,>>是追加重定向
    
    # 利用/dev/null和 > 隐藏输出结果
    $ yum -y install vim &> /dev/null
    
    # 利用/dev/null和 > 覆盖大文件
    $ cat /dev/null > /data/bigfile.log
    
  • stdin重定向

    输入重定向,将原本从终端读取键盘输入改为读取其他文件输入

    # 命令格式
    $ CMD < FILENAME
    
  • 多行重定向

    $ cat > wait.txt
    # 该命令cat会等待键盘输入
    # 然后重定向到wait.txt文件
    # 注意,一次回车就写入一次
    
    # <<EOF表示多行输入开始,EOF表示结束,且必须位于行首
    [demo@localhost ~]$ cat > file.txt <<EOF
    > this is a stdout redirect.
    > fisrt,cat commond wait stand input <<KEYWORD means muli line input begin,end of KEYWORD
    > then,cat should show in terminal,but > redirect to file.txt
    > so,this is stdout redirect.
    > hahaha,zhong shi ying yu yyds
    > EOF
    

3.4.3 标准输入字符的转换和删除

  • tr 转换或删除输入字符

    # 命令格式
    tr source_str dest_str STDIN
    
    # tr将数字转换为字母
    [demo@localhost ~]$ tr '123' 'abc'
    1234567
    abc4567
    
    # 源字段没有对应的转换字符时,默认使用目标字段的最后一个字符
    [demo@localhost ~]$ tr '12345' 'abc'
    1234567
    abccc67
    
    # 字符小写转换为大写
    [demo@localhost ~]$ tr 'a-z' 'A-Z'
    adjsigs
    ADJSIGS
    
    # -d 删除指定字符
    [demo@localhost ~]$ tr -d 'ad'
    abcdef
    bcef
    
    # -s 将指定连续重复字符去重
    [demo@localhost ~]$ tr -s 'a'
    aaaaabbbcddaaaaae
    abbbcddae
    
  • tr 实际应用

    [demo@localhost ~]$ df
    Filesystem              1K-blocks    Used Available Use% Mounted on
    /dev/mapper/centos-root  10190100 1408972   8240456  15% /
    /dev/sda1                  289285   95772    174057  36% /boot
    /dev/mapper/centos-home   7815344   35532   7359768   1% /home
    # 将多余空格转换为一个空格
    [demo@localhost ~]$ df | tr -s ' '
    Filesystem 1K-blocks Used Available Use% Mounted on
    /dev/mapper/centos-root 10190100 1408972 8240456 15% /
    /dev/sda1 289285 95772 174057 36% /boot
    /dev/mapper/centos-home 7815344 35532 7359768 1% /home
    

3.4.4 管道

  • | 的使用

    # 命令格式
    STDOUT CMD | STDIN CMD
    
    # 将前一个命令的标准输出 作为 后一个命令的标准输入
    [demo@localhost home]$ hostname | tr 'a-z' 'A-Z'
    LOCALHOST.LOCALDOMAIN
    
    # 前一个命令必须有标准输出,cd命令没有,执行结果无意义
    [demo@localhost home]$ cd demo | tr 'a-z' 'A-Z'
    
    # 后一个命令必须能接收标准输入(不能是参数),echo和pwd都不能接受标准输入
    [demo@localhost home]$ hostname | echo
    
    [demo@localhost home]$ hostname | pwd
    /home
    
  • tee 将标准输入,同时重定向到终端和文本

    # 命令格式
    tee [OPTION]... [FILE]... STDIN
    
    # 将stdin.file的内容作为tee的输入,重定向到终端和out.txt中
    [demo@localhost ~]$ tee out.file < stdin.file 
    this is stdin.file content
    as stdin of tee command
    
    # tee -a 以追加的方式重定向至文本,并在屏幕上打印
    [demo@localhost ~]$ hostname | tee -a out.file 
    localhost.localdomain
    
    [demo@localhost ~]$ cat out.file 
    this is stdin.file content
    as stdin of tee command
    localhost.localdomain
    
posted @ 2022-05-29 20:35  人间丶迷走  阅读(27)  评论(0编辑  收藏  举报