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
-
mv
和rename
的区别# -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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术