内容概述
1 文件系统目录结构
存放的是内存中正在运行的系统状态信息,数据不在硬盘而是在内存中
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
1.1 文件系统的目录结构
Linux 操作系统 ext / xfs 文件系统是区分大小写,大小写敏感
Linux的文件系统分层结构:FHS Filesystem Hierarchy Standard
参考文档:http://www.pathname.com/fhs
1.2 常见的文件系统目录结构
1.3 应用程序的组成部分
二进制程序:/bin,/sbin,/usr/bin,/usr/sbin,/usr/local/bin,/usr/local/sbin
库文件:/lib,/lib64,/usr/lib,/usr/lib64,/usr/local/lib,/usr/local/lib64
配置文件:/etc,/etc/DIRECTORY,/usr/local/etc
帮助文件:/usr/share/man,/usr/share/doc,/usr/local/share/man,/usr/local/share/doc
1.4 CentOS 7 以后版本目录结构变化
$ ls -ld /bin /usr/bin /sbin /usr/sbin
lrwxrwxrwx. 1 root root 7 Oct 30 2020 /bin -> usr/bin
lrwxrwxrwx. 1 root root 8 Oct 30 2020 /sbin -> usr/sbin
dr-xr-xr-x. 2 root root 28672 May 4 01:51 /usr/bin
dr-xr-xr-x. 2 root root 12288 May 4 01:51 /usr/sbin
1.5 Linux 下的文件类型
$ ls -l /
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
...省略...
$ ls -l /run/
total 44
-rw-------. 1 root root 11 May 4 01:50 alsactl.pid
drwxr-xr-x. 2 root root 60 May 4 01:50 dbus
prw-------. 1 root root 0 May 4 01:50 dmeventd-client
srw-rw-rw-. 1 root root 0 May 4 01:50 gssproxy.sock
...省略...
$ ls -l /dev/
total 0
crw-r--r--. 1 root root 10, 235 May 4 01:50 autofs
brw-rw----+ 1 root cdrom 11, 0 May 4 01:50 sr0
crw-rw-rw-. 1 root root 1, 5 May 4 01:50 /dev/zero
...省略...
块设备和字符设备
2 文件操作命令
2.1 显示当前工作目录
每个 Shell 和系统进程都有一个当前的工作目录 CWD:Current Word Directory
显示当前 Shell CWD 的绝对路径
pwd 命令:printing working directory
范例:
$ pwd
/root
$ ls -ld /bin /sbin /usr/bin /usr/sbin
lrwxrwxrwx. 1 root root 7 Oct 30 2020 /bin -> usr/bin
lrwxrwxrwx. 1 root root 8 Oct 30 2020 /sbin -> usr/sbin
dr-xr-xr-x. 2 root root 28672 May 4 01:51 /usr/bin
dr-xr-xr-x. 2 root root 12288 May 4 01:51 /usr/sbin
$ cd /bin
# 显示目录连接路径
$ pwd
/bin
# 显示目录真实物理路径
$ pwd -P
/usr/bin
2.2 绝对路径和相对路径
范例:
$ ls -l /etc/sysconfig/network-scripts/ifcfg-eth0
-rw-r--r--. 1 root root 130 Feb 5 2021 /etc/sysconfig/network-scripts/ifcfg-eth0
# 取绝对路径或相对路径的基名
$ basename /etc/sysconfig/network-scripts/ifcfg-eth0
ifcfg-eth0
# 在root家目录运行
$ basename ../etc/sysconfig/network-scripts/ifcfg-eth0
ifcfg-eth0
# 取绝对路径或相对路径的目录名
$ dirname /etc/sysconfig/network-scripts/ifcfg-eth0
/etc/sysconfig/network-scripts
$ dirname ../etc/sysconfig/network-scripts/ifcfg-eth0
../etc/sysconfig/network-scripts
2.3 更改目录
命令 cd:change directory
选项:-P 切换至物理路径,而非软连接目录
可以使用绝对路径或者相对路径
范例:
~ $ cd /etc/sysconfig/
/etc/sysconfig$ pwd
/data $ cd ../../data/
/data $ pwd
/data $ cd /bin/
/bin $ pwd
/bin $ cd -P /bin/
/usr/bin $ pwd
相关的环境变量:
$ pwd
/root
$ cd /bin
$ pwd
/bin
# 使用相关环境变量
$ echo $PWD
/bin
$ echo $OLDPWD
/root
# cd - 中是判断 PWD 和 OLDPWD 两个环境变量的值进行更改目录
$ pwd
/root
$ cd /bin
# 切换到/root
$ cd -
/root
# 切换到/bin
$ cd -
/bin
# 修改环境变量OLDPWD的值
$ OLDPWD=/etc/sysconfig/network-scripts/
$ cd -
/etc/sysconfig/network-scripts/
2.4 列出目录内容
ls 命令可以列出当前目录的内容或者指定目录
用法:
Usage: ls [OPTION]... [FILE]...
常见选项:
说明:
ls 查看不同后缀文件时的颜色由 /etc/DIR_COLORS 和 $LS_COLORS 变量定义
ls -l 看到文件的大小,不一定是实际文件真正占用空间的大小
范例:
# 查看当前目录下的内容
$ ls
# 文件分行并倒序显示
$ ls -lr
# 文件分行并目录递归
$ ls -lR
# 对不同类型文件显示附加不同的符号:*/=>@|
$ ls -lF
# 按从大到小排序
$ ls -lS
# 显示以访问时间为标准
$ ls -l --time=atime a.txt
# 显示以改变时间为标准
$ ls -l --time=ctime a.txt
# 列出文件后缀的颜色
$ vim /etc/DIR_COLORS
$ echo $LS_COLORS
范例:别名ll
# CentOS
$ alias ll
alias ll='ls -l --color=auto'
# Ubuntu
$ alias ll
alias ll='ls -alF'
2.5 查看文件状态:stat
文件相关信息:metadata,data
每个文件有三个时间戳:
$ stat /etc/passwd
File: ‘/etc/passwd’
Size: 1081 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 252112 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-05-05 09:14:47.401365176 +0800
Modify: 2022-05-05 09:14:47.390365103 +0800
Change: 2022-05-05 09:14:47.391365109 +0800
Birth: -
2.6 确定文件内容
文件可以包含多种类型的数据,使用 file 命令检查文件的类型,然后确定适当的打开命令或者应用程序使用
Linux 对文件的后缀不敏感,Windows 对文件的后缀敏感
格式:
Usage: file [OPTION...] [FILE...]
常用选项:
范例:windows的文本格式和linux的文本格式的区别
$ cat linux.txt
a
b
c
$ cat windows.txt
a
b
c
$ file linux.txt
linux.txt: ASCII text
$ file windows.txt
windows.txt: ASCII text, with CRLF line terminators
# 安装转换工具
$ yum install -y dos2unix
# 将windows的文本格式转换为linux的文本格式
$ dos2unix
dos2unix: converting file windows.txt to Unix format ...
$ file windows.txt
windows.txt: ASCII text
# 将linux的文本格式转换为windows的文本格式
$ unix2dos linux.txt
unix2dos: converting file linux.txt to DOS format ...
$ file linux.txt
linux.txt: ASCII text, with CRLF line terminators
范例:转换文件字符集编码
$ vim file.txt
/etc
/etc/issue
$ file -f file.txt
/etc: directory
/etc/issue: ASCII text
2.7 文件通配符 wild-card pattern
文件通配符可以用来匹配符合条件的多个文件,方便批量管理文件
通配符采用特定的符号,表示特定的含义,此特符号称为元字符,. 就是 .
常见的通配符如下:
- :匹配零个或者多个字符,但是不匹配 “.” 开头的文件,其隐藏文件
? :匹配任何单个字符,一个汉字也算一个字符
~ :当前用户家目录
~mage :用户 mage 家目录
~+ 和 . :当前工作目录
~- 和 - :前一个工作目录
[0-9] :匹配数字范围
[a-z] :匹配字母范围,匹配字母的顺序为小写字母,大写字母匹配
[A-Z] :匹配字母范围,匹配字母的顺序为大写字母,小写字母匹配
[wang] :匹配列表中的任何的一个字符
[^wang] :匹配列表中的所有字符以外的字符
另外还有在Linux系统中预定义的字符类:man 7 glob
[:alnum:]:字母和数字,示例:[[:alnum:]]
[:digit:]:十进制数字,示例:[[:digit:]]
[:punct:]:标点符号,示例:[[:punct:]]
[:alpha:]:代表任何英文大小写字符,亦即 A-Z,a-z,示例:[[:alpha:]]
[:graph:]:可打印的非空白字符,示例:[[:graph:]]
[:space:]:水平和垂直的空白字符(比[:blank:]包含的范围广),示例:[[:space:]]
[:blank:]:空白字符(空格和制表符),示例:[[:blank:]]
[:lower:]:小写字母,示例:[[:lower:]]
[:upper:]:大写字符,示例:[[:upper:]]
[:cntrl:]:不可打印的控制字符(退格,删除,警铃…)示例:[[:cntrl:]]
[:print:]:可打印字符,示例:[[:print:]]
[:xdigit:]:十六进制数字,示例:[[:xdigit:]]
范例:
$ echo "linux" > /data/linux.txt
$ echo $OLDPWD
/data
$ ls -l -/linux.txt
ls: invalid option -- '/'
Try 'ls --help' for more information.
$ ls -l ~-/linux.txt
-rw-r--r--. 1 root root 6 May 5 10:56 /data/linux.txt
范例:
$ touch f{3..4}.txt
$ ls -l f{3..5}.txt
ls: cannot access 'f5.txt': No such file or directory
-rw-r--r--. 1 root root 0 May 5 10:58 f3.txt
-rw-r--r--. 1 root root 0 May 5 10:58 f4.txt
$ ls -l f[3-5].txt
-rw-r--r--. 1 root root 0 May 5 10:58 f3.txt
-rw-r--r--. 1 root root 0 May 5 10:58 f4.txt
$ ls -l f[a-c]
-rw-r--r--. 1 root root 0 May 5 11:00 fa
-rw-r--r--. 1 root root 0 May 5 11:00 fA
-rw-r--r--. 1 root root 0 May 5 11:00 fb
-rw-r--r--. 1 root root 0 May 5 11:00 fB
-rw-r--r--. 1 root root 0 May 5 11:00 fc
$ ls -l f{a..c}
-rw-r--r--. 1 root root 0 May 5 11:00 fa
-rw-r--r--. 1 root root 0 May 5 11:00 fb
-rw-r--r--. 1 root root 0 May 5 11:00 fc
$ touch file{a..z}.txt file{A..Z}.txt file{0..9}.txt
$ ls -l file{0..9}.txt
$ ls -l file[0-9].txt
$ ls -l file[[:digit:]].txt
# 效果一致
$ ls file[a-c].txt
filea.txt fileA.txt fileb.txt fileB.txt filec.txt
$ ls file[C-E].txt
fileC.txt filed.txt fileD.txt filee.txt fileE.txt
$ ls file[wang].txt
filea.txt fileg.txt filen.txt filew.txt
$ ls file{w,a,n,g}.txt
filea.txt fileg.txt filen.txt filew.txt
$ ls file[^wang].txt
$ ls file[:lower:].txt
filee.txt filel.txt fileo.txt filer.txt filew.txt file:.txt
$ ls file[[:lower:]].txt
filea.txt filee.txt filei.txt filem.txt fileq.txt fileu.txt filey.txt
fileb.txt filef.txt filej.txt filen.txt filer.txt filev.txt filez.txt
filec.txt fileg.txt filek.txt fileo.txt files.txt filew.txt
filed.txt fileh.txt filel.txt filep.txt filet.txt filex.txt
范例:比较有无 * 的功能区别
ls -a
# * 会自动过滤掉隐藏文件和目录
ls -a *
$ alias l.
alias l.='ls -d .* --color=auto'
$ l.
$ ls -d /etc/*/
$ touch file*.log
$ touch file1.log
$ ls file*.log
file1.log 'file*.log'
$ ls 'file*.log'
'file*.log'
2.7.1 练习:
# 1、显示/etc目录下所有以l开头,以一个小写字母结尾,且中间出现至少一位数字的文件或目录
# 2、显示/etc目录下以任意一位数字开头,且以非数字结尾的文件或目录
# 3、显示/etc/目录下以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录
# 4、显示/etc/目录下所有以rc开头,并后面是0-6之间的数字,其它为任意字符的文件或目录
# 5、显示/etc目录下,所有.conf结尾,且以m,n,r,p开头的文件或目录
# 6、只显示/root下的隐藏文件和目录
# 7、只显示/etc下的非隐藏目录
# 8、只显示/etc下的隐藏文件
# 1、显示/etc目录下所有以l开头,以一个小写字母结尾,且中间出现至少一位数字的文件或目录
ls -l /etc/l*[0-9]*[[:lower:]]
ls -l /etc/l*[[:digit:]]*[[:lower:]]
# 2、显示/etc目录下以任意一位数字开头,且以非数字结尾的文件或目录
ls -l /etc/[0-9]*[^0-9]
ls -l /etc/[[:digit:]]*[^[:digit:]]
# 3、显示/etc/目录下以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录
ls -l /etc/[^a-zA-Z][a-zA-Z]*
ls -l /etc/[^[:alpha:]][[:alpha:]]*
# 4、显示/etc/目录下所有以rc开头,并后面是0-6之间的数字,其它为任意字符的文件或目录
ls -l /etc/rc[0-6]*
# 5、显示/etc目录下,所有.conf结尾,且以m,n,r,p开头的文件或目录
ls -l /etc/[mnrp]*.conf
ls -l /etc/{m,n,r,p}*.conf
# 6、只显示/root下的隐藏文件和目录
ls -ld /root/.*
# 7、只显示/etc下的非隐藏目录
ls -ld /etc/[^.]* | grep "^d"
# 8、只显示/etc下的隐藏文件
ls -ld /etc/.*
ls -ld /etc/.* | grep "^-"
2.8 创建空文件和刷新时间
touch 命令可以用来创建空文件和刷新文件的时间
格式:
touch [OPTION]... FILE ...
选项说明:
范例:
$ touch 1.txt
# 可以创建空文件,如果有文件和创建的空文件同名,也不会进行覆盖,比较安全
$ > 2.txt
# > 可以创建空文件,如果有文件和创建的空文件同名,会破坏现有的文件内容
$ touch 1.txt
$ ls -l 1.txt
-rw-r--r--. 1 root root 0 May 5 14:16 1.txt
$ touch /etc/issue
# 刷新时间
$ stat /etc/issue
File: /etc/issue
Size: 23 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 201751071 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:etc_t:s0
Access: 2022-05-05 14:20:21.208242551 +0800
Modify: 2022-05-05 14:20:21.208242551 +0800
Change: 2022-05-05 14:20:21.208242551 +0800
Birth: -
$ date
Thu May 5 14:21:09 CST 2022
$ touch `date -d "-1 day" +%F_%T`.log
$ touch $(date -d "-1 year" +%F_%T).log
# 常用做法
$ touch nginx_access_$(date +%F_%T).log
2.9 复制文件和目录
利用 cp(copy) 命令可以实现文件或者目录的复制
格式:
Usage: cp [OPTION]... [-T] SOURCE DEST
or: cp [OPTION]... SOURCE... DIRECTORY
or: cp [OPTION]... -t DIRECTORY SOURCE...
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
常用选项:
源 \目 标 | 不存在 | 存在且为文件 | 存在且为目录 |
---|---|---|---|
一个 文件 | 新建DEST,并将SRC中 内容填充至DEST中 | 将SRC中的内容覆盖至 DEST中 注意数据丢失风 险! 建议用 –i 选项 | 在DEST下新建与原文件同 名的文件,并将SRC中内容 填充至新文件中 |
多个 文件 | 提示错误 | 提示错误 | 在DEST下新建与原文件同 名的文件,并将原文件内容 复制进新文件中 |
目录 须使 用-r 选项 | 创建指定DEST同名目 录,复制SRC目录中所 有文件至DEST下 | 提示错误 | 在DEST下新建与原目录同 名的目录,并将SRC中内容 复制至新目录中 |
范例:
$ su zzw
$ echo "User zzw touch file" > /data/zzw.txt
$ ls -l zzw.txt
-rw-rw-r--. 1 zzw zzw 20 May 5 14:31 zzw.txt
$ su root
$ cp zzw.txt /opt/zzw.txt.bak
# 文件的属性发生了变化
$ ls -l /data/zzw.txt /opt/zzw.txt.bak
-rw-rw-r--. 1 zzw zzw 20 May 5 14:31 /data/zzw.txt
-rw-r--r--. 1 root root 20 May 5 14:31 /opt/zzw.txt.bak
$ cp -av /data/zzw.txt /opt/zzw.txt.backup
'/data/zzw.txt' -> '/opt/zzw.txt.backup'
$ ls -l !*
ls -l -av zzw.txt /opt/zzw.txt.backup
-rw-rw-r--. 1 zzw zzw 20 May 5 14:31 zzw.txt
-rw-rw-r--. 1 zzw zzw 20 May 5 14:31 /opt/zzw.txt.backup
$ ls -l /etc/grub2.cfg
lrwxrwxrwx. 1 root root 22 Mar 3 2021 /etc/grub2.cfg -> ../boot/grub2/grub.cfg
# 拷贝的是符号链接指定的源文件
$ cp /etc/grub2.cfg /data/
$ ls -l /data/grub2.cfg
-rw-r--r--. 1 root root 6433 May 5 14:37 /data/grub2.cfg
# 保留符号链接
$ cp -av /etc/grub2.cfg /data/grub2.cfg.bak
'/etc/grub2.cfg' -> '/data/grub2.cfg.bak'
$ ls -l /data/grub2.cfg.bak
lrwxrwxrwx. 1 root root 22 Mar 3 2021 /data/grub2.cfg.bak -> ../boot/grub2/grub.cfg
# 拷贝目录
cp -av /etc /data/etcbackup
# cp 非幂等性,即同一个命令执行多次效果一样。
# cp -av /etc /data/etcbackup 使用第二次会出现/etc 拷贝到/data/etcbackup目录下
# 拷贝文件
$ echo zzw.txt{,.bak}
zzw.txt zzw.txt.bak
$ cp -av zzw.txt{,.bak}
$ cp /data/issue{,.bak}
# -b 只能保留最新的版本
$ cp -b /etc/passwd /data/issue.bak
cp: overwrite '/data/issue.bak'? y
$ ls -l issue*
-rw-r--r--. 1 root root 23 May 5 15:33 issue
-rw-r--r--. 1 root root 2545 May 5 15:38 issue.bak
-rw-r--r--. 1 root root 23 May 5 15:36 issue.bak~
# 目标存在,覆盖前先备份加数字后缀
$ cp --backup=numbered /etc/group /data/issue.bak
cp: overwrite '/data/issue.bak'? y
$ ls -l issue*
-rw-r--r--. 1 root root 23 May 5 15:33 issue
-rw-r--r--. 1 root root 979 May 5 15:40 issue.bak
-rw-r--r--. 1 root root 23 May 5 15:36 issue.bak~
-rw-r--r--. 1 root root 2545 May 5 15:38 issue.bak.~1~
# 执行多次cp --backup=numbered,会备份多次文件并在文件后加上数字后缀
# 错误的做法
$ cp /dev/zero /data/zero
# 因为/dev/zero 是一个块设备,直接cp命令拷贝会拷贝无数个0的普通文件
# 正确的写法
$ cp -av /dev/zero /data/zero
练习:
# 1.每天将/etc/目录下所有文件,备份到/data独立的子目录下,并要求子目录格式为 backupYYYY-mm-dd,备份过程可见
# 2.创建/data/rootdir目录,并复制/root下所有文件到该目录内,要求保留原有权限
# 1.每天将/etc/目录下所有文件,备份到/data独立的子目录下,并要求子目录格式为 backupYYYY-mm-dd,备份过程可见
mkdir -pv /data
cp -av /etc /data/backup$(date +%F)
# 2.创建/data/rootdir目录,并复制/root下所有文件到该目录内,要求保留原有权限
mkdir -pv /data/rootdir
cp -av /root/* /data/rootdir
2.10 移动和重命名文件
mv (move)命令可以实现文件或者目录的移动和改名。
同一分区移动数据,速度很快(数据位置没有变化)
不同分区移动数据,速度相对慢(数据位置发生了变化)
格式:
Usage: mv [OPTION]... [-T] SOURCE DEST
or: mv [OPTION]... SOURCE... DIRECTORY
or: mv [OPTION]... -t DIRECTORY SOURCE...
Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
常用选项:
命令格式 | 运行结果 |
---|---|
mv source_file(文件) dest_file(文件) | 将源文件名 source_file 改为目标文件名 dest_file |
mv source_file(文件) dest_directory(目录) | 将文件 source_file 移动到目标目录 dest_directory 中 |
mv source_directory(目录) dest_directory(目录) | 目录名 dest_directory 已存在,将 source_directory 移动到目录名 dest_directory 中;目录名 dest_directory 不存在则 source_directory 改名为目录名 dest_directory |
mv source_directory(目录) dest_file(文件) | 出错 |
可以利用 rename 可以批量修改文件名
格式:
Usage:
rename [options] <expression> <replacement> <file>...
范例:
# 为所有的conf文件添加上 .bak 后缀
$ touch f{1..5}.conf
$ rename "conf" "conf.bak" f*
$ ls
f1.conf.bak f2.conf.bak f3.conf.bak f4.conf.bak f5.conf.bak
# 去掉所有的 .bak 后缀
$ rename ".bak" "" f*
$ rename "conf.bak" "conf" f*
# 将文件 aaa 改名为 bbb
mv aaa bbb
# 将info 目录放入 logs 目录中。注意,如果 logs 目录不存在,则该命令将 info 改名为 logs
mv info/ logs
# 再如将 /usr/runoob 下的所有文件和目录移到当前目录下,命令行为
mv /usr/runoob/* .
2.11 删除文件
使用 rm(remove) 命令可以删除文件
注意:此命令非常危险,慎重使用,建议使用 mv 代替 rm
格式:
Usage: rm [OPTION]... [FILE]...
常用选项:
范例:
$ rm -rf /data/etc
$ alias rm
alias rm='rm -i'
### 注意千万不能使用 rm -rf /*
$ rm -rf /
rm: it is dangerous to operate recursively on ‘/’
rm: use --no-preserve-root to override this failsafe
# 思考删除/下的文件,如何进行验证
$ rm -rf /* # 真的可以删除 / 下所有的文件和目录
$ echo *
$ echo /*
范例:删除特殊文件
$ rm --help
...省略...
To remove a file whose name starts with a '-', for example '-foo',
use one of these commands:
rm -- -foo
rm ./-foo
# 将名为 “/data/-f” 的文件删除
### 遇到不正常的文件名,建议统一使用绝对路径或者相对路径进行删除操作
$ rm -rf -f # 此方法错误
# 正确的做法
$ rm -rf -- -f
$ rm -rf # 使用绝对路径或者相对路径(rm ./-f | rm /data/-f)
$ touch '~'
$ rm -f ~
rm: cannot remove '/root': Is a directory
$ rm -- ~
rm: cannot remove '/root': Is a directory
$ rm -rf ./~
$ cp /dev/zero /boot/bigfile.img
$ df -Th | grep boot
/dev/sda1 xfs 2.0G 2.0G 32K 100% /boot
$ ls -lhS /boot/
total 2.0G
-rw-r--r--. 1 root root 1.8G May 5 20:42 bigfile.img # 没有用的垃圾文件
$ vim /boot/bigfile.img # 新开终端执行
$ rm -rf /boot/bigfile.img
$ ls -lhS /boot | grep bigfile.img # 已经删除了大文件
# boot的分区利用率依旧是100%
$ df -Th | grep boot
/dev/sda1 xfs 2.0G 2.0G 32K 100% /boot
$ w
20:51:33 up 19 min, 2 users, load average: 1.00, 0.67, 0.31
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.0.0.1 20:32 1.00s 0.22s 0.01s w
root pts/1 10.0.0.1 20:46 5:09 4:52 4:52 vim /boot/bigfile.img
# lsof 是一个列出当前系统打开文件的工具。
$ lsof | grep delete
vim 2530 root 5r REG 8,1 1880358912 34154 /boot/bigfile.img (deleted)
# boot的分区利用率将下降了
$ kill -9 2530
$ df -Th | grep boot
/dev/sda1 xfs 2.0G 245M 1.8G 13% /boot
$ dd if=/dev/zero of=/boot/bigfile.img
$ > /boot/bigfile.img # 但是该 > 依赖于Shell
### 更加通用的做法:什么Shell都支持
cat /dev/null > /boot/bigfile.img
$ df -Th
/dev/sda1 xfs 2.0G 245M 1.8G 13% /boot
$ rm -rf /boot/bigfile.img
shred 命令完全删除文件
rm 虽然删除了文件,但是被删除 的文件仍然可能被恢复,在安全要求较高的场景下,可以使用 shred 安全删除文件。
格式:
Usage: shred [OPTION]... FILE...
Overwrite the specified FILE(s) repeatedly, in order to make it harder
for even very expensive hardware probing to recover the data.
常见选项:
$ shred -zvun 5 passwd.txt
shred: passwd.txt: pass 1/6 (random)...
shred: passwd.txt: pass 2/6 (000000)...
shred: passwd.txt: pass 3/6 (random)...
shred: passwd.txt: pass 4/6 (ffffff)...
shred: passwd.txt: pass 5/6 (random)...
shred: passwd.txt: pass 6/6 (000000)...
shred: passwd.txt: removing
shred: passwd.txt: renamed to 0000000000
shred: 0000000000: renamed to 000000000
shred: 000000000: renamed to 00000000
shred: 00000000: renamed to 0000000
shred: 0000000: renamed to 000000
shred: 000000: renamed to 00000
shred: 00000: renamed to 0000
shred: 0000: renamed to 000
shred: 000: renamed to 00
shred: 00: renamed to 0
shred: passwd.txt: removed
$ ls passwd.txt
ls: cannot access 'passwd.txt': No such file or directory
2.12 目录操作
2.12.1 显示目录树 tree
tree:以树状图列出当前目录结构
常见选项:
$ tree
.
├── dir1
│ ├── dir2
│ │ └── dir4
│ └── dir3
│ └── dir4
├── group
└── passwd.txt
5 directories, 2 files
$ tree -dp
.
└── [drwxr-xr-x] dir1
├── [drwxr-xr-x] dir2
│ └── [drwxr-xr-x] dir4
└── [drwxr-xr-x] dir3
└── [drwxr-xr-x] dir4
5 directories
2.12.2 创建目录 mkdir
常见选项:
2.12.3 删除空目录 rmdir
常见选项:
注意:rmdir 只能删除空目录,如果想删除非空目录,可以使用 rm -r 命令,递归删除目录树
范例:
alias rm='DIR=/data/backup`date +%F_%T`;mkdir $DIR;mv -t $DIR'
2.12.4 练习
# (1) 如何创建/testdir/dir1/x, /testdir/dir1/y, /testdir/dir1/x/a, /testdir/dir1/x/b, /testdir/dir1/y/a,/testdir/dir1/y/b
# (2) 如何创建/testdir/dir2/x, /testdir/dir2/y, /testdir/dir2/x/a, /testdir/dir2/x/b
# (3) 如何创建/testdir/dir3, /testdir/dir4, /testdir/dir5, /testdir/dir5/dir6, /testdir/dir5/dir7
# (1) 如何创建/testdir/dir1/x, /testdir/dir1/y, /testdir/dir1/x/a, /testdir/dir1/x/b, /testdir/dir1/y/a,/testdir/dir1/y/b
mkdir -pv /testdir/dir1/{x,y}/{a,b}
# (2) 如何创建/testdir/dir2/x, /testdir/dir2/y, /testdir/dir2/x/a, /testdir/dir2/x/b
mkdir -pv /testdir/dir2/{x/{a,b},y}
mkdir -pv /testdir/dir2/x/{a,b} /testdir/dir2/y
# (3) 如何创建/testdir/dir3, /testdir/dir4, /testdir/dir5, /testdir/dir5/dir6, /testdir/dir5/dir7
mkdir -pv /testdir/dir{3,4,5/dir{6,7}}
mkdir -pv /testdir/dir{3,4,5} /testdir/dir5/dir{6,7}
## 可以用tree命令查看创建的目录
3 文件元数据和节点表结构
3.1 inode 表结构
每个文件的属性信息 meta data,比如:文件的大小,时间,类型,权限等等,称为文件的元数据(meta data)。这些元数据是存放在 node(index node)表中。node 表中有很多条记录组成,第一条记录对应的存放了一个文件的元数据信息。
第一个 node 表记录对应的保存了以下信息:
在硬盘的分区上,有一块空间用来存放文件和目录的元数据metadata,有一块空间用来存放真正的数据data
元数据的存放,每一个文件的元数据信息存放,被称为 inode 表。inode 表包含以下信息:
- inode number 节点号
- 文件类型
- UID
- GID
- 链接数(指向这个文件名路径名称个数)
- 该文件的大小和不同的时间戳
- 指向磁盘上文件的数据块指针
- 有关文件的其他数据
文件的元数据信息和真正的数据存放位置不同,所以就需要有数据指针(地址)来引导寻找真正数据的位置
指针可以分为:直接块指针、间接块指针、双重间接块指针、三重间接块指针
而每一个磁盘上存放数据的空间,会有一个分配单位:block 块(block 的大小通常是4K = 4096字节)
- 直接块指针:就是直接使用指针就找到了文件数据真实存放的位置;直接块指针一共有 12 个,12个指针就可以分别指向 12 个块 block;那么就是 12 * 4 = 48K 的数据。也就是说 直接块指针可以存放 48K 以内的数据内容。
- 间接块指针:当文件超过48K的数据大小,那么就会用到间接块指针;间接块指针是会指定到一个指针块 block 中,指针块也是 4K(4096 字节),指针块中一个小块就是占用空间为 4 个字节,那么指针块可以存放 1024 个指针。那么 1024 个指针指向的数据块存放为 4K,那么间接块指针可以存放 1024 * 4K = 4M。也就是说 间接块指针可以存放 4M 以内的数据内容。
- 双重间接块指针同理。跟套娃一样。那么双重间接块指针可以存放 1024 * 1024 * 4K = 4G。也就是说 双重间接块指针可以存放 4G 以内的数据内容。
- 三重间接块指针同理。也就是说 三重间接块指针可以存放 4T 以内的数据内容。
数据越大,指针就不是直接指向数据了,需要通过间接的手段实现。那么文件越大,找起来会慢。
Linux 操作系统中的文件系统在对底层元数据 metadata 和真实数据 data 的实现方式上各有不同之处。
在磁盘上,每个文件都会有一个与众不同的唯一标识,叫 inode number节点号;就像每个人都会唯一的身份证号一样。节点号是一个整数;就是文件的节点号来标识文件;节点号是每个分区独立分配的;
节点号也是宝贵的资源,每创建一个目录或者文件,都会消耗一个节点号
# 查看系统节点表空间利用率
$ df -Thi
# 查看物理分区空间利用率
$ df -Th
$ ls -il /data
total 0
131 -rw-r--r--. 1 root root 0 May 5 22:15 f1.txt
132 -rw-r--r--. 1 root root 0 May 5 22:15 f2.txt
133 -rw-r--r--. 1 root root 0 May 5 22:15 f3.txt
$ df -ih
Filesystem Inodes IUsed IFree IUse% Mounted on
devtmpfs 457K 402 457K 1% /dev
tmpfs 464K 1 464K 1% /dev/shm
tmpfs 464K 858 463K 1% /run
tmpfs 464K 17 464K 1% /sys/fs/cgroup
/dev/sda2 50M 121K 50M 1% /
/dev/sda3 50M 9 50M 1% /data
/dev/sda1 1.0M 309 1.0M 1% /boot
tmpfs 464K 23 464K 1% /run/user/42
tmpfs 464K 11 464K 1% /run/user/0
# 不同的分区中分配的节点号可以相同。就像中国和印度可能会出现身份证号一样的情况,但是用来标识不同的人
# 同一个分区中分配的节点号可能会有重复,即同一个文件有多个名,比如硬链接。在磁盘上占用的空间是一份
$ ls -il /data | grep 131
131 -rw-r--r--. 1 root root 0 May 5 22:15 f1.txt
$ ls -il /boot | grep 131
131 drwxr-xr-x. 3 root root 17 Jul 11 2021 efi
目录
目录是个特殊文件,文件内容保存了目录中文件的列表及 inode number
inode 表和目录
目录是特殊的文件。
目录的元数据跟文件的元数据大致相同,只是在指针指向中,目录的指针指向的数据。目录的数据部分是目录下所有文件的列表(列表存放的是文件名+节点号)
cp 和 inode
cp 命令:
rm 和 inode
rm 命令:
mv 和 inode
$ touch file{1..n}.txt
-bash: /usr/bin/touch: Argument list too long
# 正确的写法
echo file{1..n}.txt | xargs touch
# 删除大量的空文件
echo file{1..n}.txt | xargs rm
节点编号用光的情况:只有分区中有大量的无用的小文件占用
解决方法:
- 删除分区中无用的小文件
- 修改inode的数量(注意该方法会丢失磁盘数据,建议操作前备份数据)
3.2 硬(Hard)链接
ln(link)
Usage: ln [OPTION]... [-T] TARGET LINK_NAME
or: ln [OPTION]... TARGET
or: ln [OPTION]... TARGET... DIRECTORY
or: ln [OPTION]... -t DIRECTORY TARGET...
硬链接本质上就给一个文件起一个新的名称,实质就是同一个文件
硬链接特性:
格式:
ln filename [linkname]
$ cp /etc/fstab /data/dir/f1.txt
$ ls -i dir/f1.txt
132 -rw-r--r--. 1 root root 709 May 7 20:17 /data/dir/f1.txt
$ ln /data/dir/f1.txt /data/f11.txt
$ ls -li !*
ls -li /data/dir/f1.txt /data/f11.txt
132 -rw-r--r--. 2 root root 709 May 7 20:17 /data/dir/f1.txt
132 -rw-r--r--. 2 root root 709 May 7 20:17 /data/f11.txt
节点号 权限 连接数
# 在文件中追加数据或者删除数据都会进行同步操作,本质上是一个文件。
# 不能跨越驱动器或分区
$ ln /data/f11.txt /opt/f11.txt
ln: failed to create hard link '/opt/f11.txt' => '/data/f11.txt': Invalid cross-device link
# 不支持对目录创建硬链接
$ ln /data/dir/ /data/dir2
ln: /data/dir/: hard link not allowed for directory
# 删除硬链接或者源文件时,并没有依赖关系,但是会减少链接数
### 如何一个目录的连接数至少是 2.
3.3 符号symbolic(或者软soft)链接
一个符号链接指向另一个文件,就像 windows 中快捷方式,软连接文件和源文件本质上不是同一个文件。
软连接特点:
格式:
ln -s filename [linkname]
范例:
$ ln -sv /data/f11.txt /data/dir/f11.txt
$ ls -li !*
ls -li -sv /data/f11.txt /data/dir/f11.txt
软链接大小跟指向路径有关/data/f11.txt
133 0 lrwxrwxrwx. 1 root root 13 May 7 20:31 /data/dir/f11.txt -> /data/f11.txt
132 4 -rw-r--r--. 1 root root 718 May 7 20:21 /data/f11.txt
# 删除源文件,软链接将无法使用,源文件和软链接有依赖关系。
$ rm -rf /data/f11.txt
$ ls -li /data/dir/f11.txt
133 lrwxrwxrwx. 1 root root 13 May 7 20:31 /data/dir/f11.txt -> /data/f11.txt(源文件失效)
# 可以跨分区的文件实现
$ ln -s /data/dir/f11.txt /opt/f111.txt
$ ls -li -s /data/dir/f11.txt /opt/f111.txt
133 0 lrwxrwxrwx. 1 root root 13 May 7 20:31 /data/dir/f11.txt -> /data/f11.txt
1877679 0 lrwxrwxrwx. 1 root root 17 May 7 20:34 /opt/f111.txt -> /data/dir/f11.txt
# 可以对目录创建软连接
# 使用绝对路径
ln -sv /data/dir/ /data/dirlink
# 相对路径使用
cd /data/
ln -sv ../data/dir /root/dirlink
rm -rf /data/dirlink # 删除软连接本身,不会删除源目录内容
rm -rf /data/dirlink/ # 删除源目录的文件,不会输出链接文件
# 查看链接文件指向的源文件
readlink /data/dirlink
$ readlink /proc/1/exe
/usr/lib/systemd/systemd
$ ls -l /proc/1/exe
lrwxrwxrwx. 1 root root 0 May 7 19:53 /proc/1/exe -> /usr/lib/systemd/systemd
3.4 硬链接和软链接区别总结
1 本质:
2 跨设备:
3 inode 节点号:
4 链接数:
5 文件夹:
6 相对路径
7 删除源文件
8 文件类型
9 文件大小
3.5 生产案例
3.5.1 案例1:提示空间满 No space left on device,但是 df 可以看到空间很多,为什么?
原因有:磁盘空间占满或者是磁盘节点编号占满
3.5.2 案例2:提示空间快满了,使用 rm 删除了很大的无用文件之后,df 仍然看到空间不足,为什么?如何解决?
4 IO重定向和管道
4.1 标准输入和输出
程序:指令 + 数据
读入数据:Input
输出数据:Output
打开的文件都有一个fd :file descriptor(文件描述符)
Linux给程序提供了三种 I/O 设备:
范例:文件描述符
# 可以在/dev目录下查看到标准
$ ls -l /dev/std*
lrwxrwxrwx 1 root root 15 May 3 20:32 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 3 20:32 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 May 3 20:32 /dev/stdout -> /proc/self/fd/1
# 查看进程信息
$ ls -l /proc/self/fd/*
ls: cannot access /proc/self/fd/255: No such file or directory
ls: cannot access /proc/self/fd/3: No such file or directory
lrwx------ 1 root root 64 May 7 21:06 /proc/self/fd/0 -> /dev/pts/0
lrwx------ 1 root root 64 May 7 21:06 /proc/self/fd/1 -> /dev/pts/0
lrwx------ 1 root root 64 May 7 21:06 /proc/self/fd/2 -> /dev/pts/0
$ ls -l /proc/$(pidof tail)/fd
total 0
lrwx------ 1 root root 64 May 7 21:07 0 -> /dev/pts/1
lrwx------ 1 root root 64 May 7 21:07 1 -> /dev/pts/1
lrwx------ 1 root root 64 May 7 21:07 2 -> /dev/pts/1
# 标准输出重定向
$ ls -l > /dev/pts/1 & ls -l 1> /dev/pts/1
# 标准错误重定向
$ ks 2> /dev/pts/1
$ rm f1.txt
rm: remove regular file ‘f1.txt’? # 属于标准错误
# 所谓的错误不一定是真正的错误,有可能是警告或者是报警信息
# 标准输出到其他终端一般会需要root权限
4.2 IO重定向 redirect
I/O 重定向:将默认的输入,输出或者错误对应的设备改变,指向新的目标
4.2.1 标准输出和错误重定向
STDOUT 和 STDERR 可以被重定向到指定文件,而非默认的当前终端
格式:
命令 操作符号 文件名
支持的操作符号包括:
1> 或者 > :把 STDOUT 重定向到文件
>| :强制覆盖
2> :把 STDERR 重定向到文件
&> : 把所有输出重定向到文件
>& :和上面的功能一样,建议使用上面的方式
以上如果文件已经存在,文件内容会被覆盖
set -C:禁止将内容覆盖已有文件,但是可以追加,可以利用 >| 仍然可以强制覆盖
set +C:运行覆盖
>> :可以在原有内容基础上,追加内容
追加
可以在原有内容基础上,追加内容
把输出和错误重新定向追加到文件中
>> :追加标准输出重定向至文件
2>>:追加标准错误重定向至文件
标准输出和错误输出各自定向至不同位置
COMMAND > /PATH/TO/file.out 2> /PATH/TO/error.out
合并标准输出和错误输出为同一个数据流进行重定向
&> :覆盖重定向
&>>:追加重定向
COMMAND > /PATH/TO/file.out 2>&1 (顺序很重要)
COMMAND 2> /PATH/TO/file.out 1>&2 (顺序很重要)
COMMAND >> /PATH/TO/file.out 2>&1
合并多个程序
(CMD1;CMD2;…) 或者 {CMD1;CMD2;…;} 合并多个程序的 STDOUT
范例:
ls 1> /dev/pts/1
ls /data > /dev/pts/1
范例:标准错误重定向
# 根据Shell终端类型有关
rm f1.txt 2> /data/all.log
范例:合并多个命令的结果至一个文件中
( cal 2019;cal 2020 ) > all.txt
{ ls -l;hostname } > all.txt
范例:清除大文件
cat /dev/null > /root/linux/bigfile.img
> /root/linux/bigfile.img
范例:分别重定向
ls -l /data /xxx 1> stdout.log 2> error.log
范例:将标准输出和标准错误都重定向到同一个文件
## 如果没有定义标准输出和标准错误重定向规则,就会默认输出到终端屏幕中
## 2>&1 &为了表示后面的数字代表文件描述符
# ls /data /xxx > /data/all.log 2>&1
# ls /data /xxx 2> /data/all.log 1>&2
# ls /data /xxx &> /data/all.log
# ls /data /xxx >& /data/all.log
## 因为在2>&1 并不知道标准错误是存放在哪里,默认在终端上显示。则标准错误就打印在终端中
# ls /data /xxx 2>&1 > /data/all.log
ls: cannot access /xxx: No such file or directory
范例:
$ man bash > man_bash.txt
$ wc -l man_bash.txt
4200 man_bash.txt
范例:
$ curl http://www.wangxiaochun.com/testdir/hello.sh
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 2017/06/01
# Author: wang
# Email: 29308620@qq.com
# Website: www.wangxiaochun.com
# Description: This is the first script
# Copyright: 2017 wang
# License: GPL
# ------------------------------------------
#经典写法
echo "hello, world"
#流行写法
echo 'Hello, world!'
$ curl http://www.wangxiaochun.com/testdir/hello.sh 1> f1.log 2> f2.log
$ ls -l f*
-rw-r--r-- 1 root root 420 May 8 00:01 f1.log
-rw-r--r-- 1 root root 317 May 8 00:01 f2.log
$ cat f1.log
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 2017/06/01
# Author: wang
# Email: 29308620@qq.com
# Website: www.wangxiaochun.com
# Description: This is the first script
# Copyright: 2017 wang
# License: GPL
# ------------------------------------------
#经典写法
echo "hello, world"
#流行写法
echo 'Hello, world!'
$ cat f2.log
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 420 100 420 0 0 3985 0 --:--:-- --:--:-- --:--:-- 4000
范例:屏幕不输出修改密码信息
passwd zzw &> /dev/null
范例:实现标准输出和错误的互换
$ (cat /etc/centos-release /etc/xxx 3>&1 1>&2 2>&3) > f1.txt 2> f2.txt
$ cat f1.txt
cat: /etc/xxx: No such file or directory
$ cat f2.txt
CentOS Linux release 7.9.2009 (Core)
4.2.2 标准输入重定向
从文件中导入 STDIN,代替当前终端的输入设备,使用 < 来重定向标准输入某些命令能够接受从文件中导入的 STDIN
所谓的标准输入就是不是通过人为的交互式的方式把输入信息输到计算机程序里面,而是提前准备一个文件,将需要的输入信息写入到文件中,再将该文件导入到标准输入程序
范例:
$ seq -s + 100 > bc.txt
$ bc < bc.txt
5050
# mail 可以给当前机器上的用户发送邮件
$ yum install -y mailx postfix
$ systemctl enable --now postfix
$ mail -s hello zzw
I am root
Hello
. # (.句号结束)
EOT
# 标准输入重定向
$ cat > mail_template.txt <<-'EOF'
Hello!
I am root
Congratulations! You Login sccessfully
Don't play fire!
EOF
$ mail -s "Give you" zzw < mail_template.txt
### 使用mail实现QQ邮箱发送
# QQ邮箱授权码:yxmomqzszmblbcad
# 需要配置mail配置文件
vim /etc/mail.rc
### 在最后添加以下内容
# 发邮件时 用户的邮箱
set from=935523993@qq.com
# 发邮件时 使用的邮箱服务器地址
set smtp=smtp.qq.com
# 发邮件时 使用的用户
set smtp-auth-user=935523993@qq.com
# 发邮件时 使用的密码(授权码)
set smtp-auth-password=yxmomqzszmblbcad
$ mail -s "Test mail" 935523993@qq.com < mail_template.txt
4.2.2.1 tr 命令
tr 转换和删除字符
tr [OPTION]... SET1 [SET2]
选项:
\NNN character with octal value NNN (1 to 3 octal digits)
\\ backslash
\a audible BEL
\b backspace
\f form feed
\n new line
\r return
\t horizontal tab
\v vertical tab
[:alnum:]:字母和数字(all letters and digits)
[:alpha:]:字母(all letters)
[:cntrl:]:控制(非打印)字符(all control characters)
[:digit:]:数字(all digits)
[:graph:]:图形字符(all printable characters, not including space)
[:lower:]:小写字母(all lower case letters)
[:print:]:可打印字符(all printable characters, including space)
[:punct:]:标点符号(all punctuation characters)
[:space:]:空白字符(all horizontal or vertical whitespace)
[:upper:]:大写字母(all upper case letters)
[:xdigit:]:十六进制字符(all hexadecimal digits)
范例:
# 该命令会把/etc/centos-release中的小写字符转换为大写字符
tr 'a-z' 'A-Z' < /etc/centos-release
# 删除fstab文件中的所有abc中的任意字符
tr -d abc < /etc/fstab
$ df
$ df > df.log
$ tr -s " " < df.log
范例:将Windows的文本转化为Linux的文本格式
$ cat windows.txt
a
b
c
windows.txt
$ file windows.txt
windows.txt: ASCII text, with CRLF line terminators
$ hexdump -C windows.txt
00000000 61 0d 0a 62 0d 0a 63 0d 0a 77 69 6e 64 6f 77 73 |a..b..c..windows|
00000010 2e 74 78 74 |.txt|
00000014
# windows文本格式与linux文本格式间的转换,windows格式文本中比linux格式文本中多回车键'\r',通过tr删除'\r'实现格式转换
$ tr -d "\r" < windows.txt > windows-linux.txt
$ hexdump -C windows-linux.txt
00000000 61 0a 62 0a 63 0a 77 69 6e 64 6f 77 73 2e 74 78 |a.b.c.windows.tx|
00000010 74 |t|
00000011
$ file windows-linux.txt
windows-linux.txt: ASCII text
思考:将Linux的文本转换为 Windows 的文本格式?
注意:不能使用 tr 命令将文件从 Unix 格式转换为 Windows(DOS)。
除此之外Linux还提供了两种文本格式相互转化的命令:dos2unix和unix2dos,dos2unix把"\r\n"转化成"\n",unix2dos把"\n"转化成"\r\n"。
4.2.2.2 标准输入重定向
实现标准输入重定向的符号
COMMAND 0< FILE
COMMAND < FILE
比如:
cat < /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
按 Ctrl + D离开,可以使用文件来代替键盘的输入
cat < file1 > file2
cat < file1 >> file1
范例:
$ echo "2^3" > bc.log
$ bc < bc.log
8
$ cat > mail_template.txt
Hello!
I am root
Congratulations! You Login sccessfully
Don't play fire!
$ cat < mail_template.txt > mail_template2.txt
$ mail -s "Test mail" zzw < mail_template.txt
$ cat > cat.log
line1
line2
line3
4.2.2.3 把多行重定向
使用 “<< 终止词” 命令 从键盘把多行重导向给 STDIN,直到终止词位置之前的所有文本都发送给 STDIN,有时被称为就地文本(here documents)。
其中终止词可以是任何一个或者多个符号,比如:!,@,$,EOF(End Of File),magedu 等等,其中 EOF 比较常用。
范例:
$ mail -s "Please Call" root <<EOF
> Hi wang
>
> Please give me a call when you get in.Wey may need
> to do some maintenance on server1
>
> Details where you're on-site
> Zhong
> EOF
# 查看邮件
4.3 管道
4.3.1 管道
管道(使用符号 “|” 表示)用来连接多个命令;
格式:
命令1 | 命令2 | 命令3 | ......
功能说明:
注意:STDERR 默认不能通过管道转发,可以利用 2>&1 或者 |& 实现,格式如下:
命令1 2>&1 | 命令2
命令1 |& 命令2
范例:非交互式修改用户密码
# 方法1
$ passwd --stdin wang
Changing password for user wang.
Admin@h3c
passwd: all authentication tokens updated successfully.
# 方法2
$ echo "Admin@h3c" > wang-password.txt
$ passwd --stdin wang < wang-password.txt
# 方法3:
$ cat wang-password.txt | passwd --stdin wang
# 方法4:
echo "Admin@h3c" | passwd --stdin wang
echo "Admin@h3c" | passwd --stdin wang &> /dev/null
范例:
# 将小写字母转换为大写字母
ls | tr 'a-z' 'A-Z'
# less 实现分页的查看输入
ls -l /etc/ | less
# mail通过电子邮件发送输入
echo "Test mail" | mail -s 'Test mail' 935523993@qq.com
# 算数运算
echo "2^3" | bc
4.3.2 tee 命令
利用 tee 命令可以重定向到多个目标(tee 命令即将输出重定向到文件也将输出的信息显示出来),经常配合管道符一起使用
格式:
命令1 | tee [-a] 文件名 | 命令2
以上可以把命令1 的 STDOUT 保存在文件中,做为命令2 的输入
选项:
功能:
范例:
echo {1..100} | tr " " + | bc
echo {1..100..2} | tr " " + | bc
seq -s + 100 | bc
seq -s + 1 2 100 | bc
范例:
cat << | tee -a /etc/mail.rc
# 发邮件时 用户的邮箱
set from=935523993@qq.com
# 发邮件时 使用的邮箱服务器地址
set smtp=smtp.qq.com
# 发邮件时 使用的用户
set smtp-auth-user=935523993@qq.com
# 发邮件时 使用的密码(授权码)
set smtp-auth-password=yxmomqzszmblbcad
set smtp-auth=login
set ssl-verify=ignore
EOF
cat <<EOF | tee /etc/motd
> The hostname is kubesphere-docker.io
> Don't play fire!!!
> EOF
The hostname is kubesphere-docker.io
Don't play fire!!!
4.4 重定向中的 - 符号
重定向有时会有使用 - 符号
范例:
# -O 指定下载后的文件名
wget -O hello.sh http://www.wangxiaochun.com/testdir/hello.sh
# - 重定向到当前屏幕中,而非保存到文件中
# - 将保存的文件内容输出到屏幕中,与 > 标准输出相反
wget -O - http://www.wangxiaochun.com/testdir/hello.sh
wget -qO - http://www.wangxiaochun.com/testdir/hello.sh
范例:
将 /home 里面的文件打包,但是打包的数据不是记录到文件,而是传送到 stdout,经过管道后,将 tar -cvf - /home 传送给后面的 tar -xvf -,后面的这个 - 则是取前面一个命令的 stdout,因此,就不需要使用临时的file了
# 原始命令
tar -cvf home.tar /home ; tar -xvf home.tar
# 少个中间的产物
tar -cvf - /home | tar -xvf -
4.5 练习
# 1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
# 2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中
# 3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:
# 4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开
# 5、计算1+2+3+...+99+100的总和
# 6、删除Windows文本文件中的回车字符 ,即“\r”
# 7、处理字符串“xt.,l 1 jr#!$mn 2 c*/fe 3 uz 4”,只保留其中的数字和空格
# 8、将PATH变量每个目录显示在独立的一行
# 9、将指定文件中0-9分别替代成a-j
# 10、将文件/etc/centos-release中每个单词(由字母组成)显示在独立一行,并无空行
# 1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
# 方法1:
$ cat /etc/issue | tr -s [:lower:] [:upper:] > /tmp/issue.out
$ cat /tmp/issue.out
\S
KERNEL \R ON AN \M
# 方法2:
$ tr "a-z" "A-Z" < /etc/issue > /tmp/issue.out
# 2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中
$ who | tr -s [:lower:] [:upper:] > /tmp/who.out
# 3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:
## Hello, I am 用户名,The system version is here,please help me to check it ,thanks!
## 操作系统版本信息
# 方法1:
$ vim mail.txt
Hello,
I am $(whoami),The system version is here,please help me to check it ,thanks!
$(cat /etc/os-release)
$ mail -s 'help' root < mail.txt
# 方法2:
$ cat <<EOF | mail -s 'help' root
> Hello,
> I am `whoami` ,The system version is here,please help me to check it ,thanks!
> `cat /etc/centos-release`
> EOF
# 4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开
$ ls -l /root/ | tr -s "\n" " "
$ ls /root | tr -s "\n" " "
# 5、计算1+2+3+...+99+100的总和
# 方法1:
$ echo {1..100} | tr -s " " + | bc
5050
# 方法2:
$ seq -s "+" 100 | bc
5050
# 6、删除Windows文本文件中的回车字符 ,即“\r”
$ file windows.txt
windows.txt: ASCII text, with CRLF line terminators
$ hexdump -C windows.txt
00000000 77 69 6e 64 6f 77 73 0d 0a 61 0d 0a 62 0d 0a 63 |windows..a..b..c|
00000010
$ tr -d "\r" < windows.txt > linux.txt
$ hexdump -C linux.txt
00000000 77 69 6e 64 6f 77 73 0a 61 0a 62 0a 63 |windows.a.b.c|
0000000d
# 7、处理字符串"xt.,l 1 jr#!$mn 2 c*/fe 3 uz 4",只保留其中的数字和空格
$ echo "xt.,l 1 jr#!$mn 2 c*/fe 3 uz 4" | tr -dc "0-9 "
$ echo "xt.,l 1 jr#)mn 2 c*/fe 3 uz 4" | tr -dc [0-9][[:space:]]
$ echo "xt.,l 1 jr#windows.txtmn 2 c*/fe 3 uz 4" | dc "[[:digit:][:space:]]"
# 8、将PATH变量每个目录显示在独立的一行
$ echo $PATH | tr -s ":" "\n"
# 9、将指定文件中0-9分别替代成a-j
$ echo "1234567890987654321" > number.txt
$ tr "0-9" "a-j" < number.txt
# 10、将文件/etc/centos-release中每个单词(由字母组成)显示在独立一行,并无空行
$ cat /etc/centos-release | tr -s " " "\n" | tr -dc "a-zA-Z\n"
CentOS
Linux
release