1.标准输入和输出
1.1程序的三个I/O设备文件
1.1.1.标准输入(STDIN)
文件描述符:0 默认接受来自终端窗口
1.1.2.标准输出(STDOUT)
文件描述符:1 默认输出到终端窗口
1.1.3.标准错误(STDERR)
文件描述符:2 默认输出到终端窗口
练习:
使用ps aux无法看到有些程序路径,这时如何查找到其路径?
#利用ps aux找到其PID,使用echo $$命令输出当前终端PID
[root@Centos7 ~]# echo $$
1708
#proc目录下exe指向的就是程序所在路径
[root@Centos7 ~]# ll /proc/$$ | grep exe
lrwxrwxrwx. 1 root root 0 Dec 14 06:12 exe -> /usr/bin/bash
#fd(file descriptor)文件夹中可以查看当前程序的文件描述符
[root@Centos7 ~]# cd /proc/$$/fd
[root@Centos7 fd]# ll
total 0
lrwx------. 1 root root 64 Dec 14 00:44 0 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 14 00:44 1 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 14 00:44 2 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 14 06:24 255 -> /dev/pts/0
文件描述符查看(默认当前终端窗口)
[root@Centos7 fd]# ll /dev/std*
lrwxrwxrwx. 1 root root 15 Dec 13 22:34 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 Dec 13 22:34 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 Dec 13 22:34 /dev/stdout -> /proc/self/fd/1
[root@Centos7 fd]# ll /proc/self/fd
total 0
lrwx------. 1 root root 64 Dec 14 06:57 0 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 14 06:57 1 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 14 06:57 2 -> /dev/pts/0
lr-x------. 1 root root 64 Dec 14 06:57 3 -> /proc/2470/fd
2.I/O重定向(redirect)
2.1标准输出重定向
会覆盖文件的操作符
1> > 把标准输出(STDOUT)重定向到文件
2> 把标准错误(STDERR)重定向到文件
&> 把所有输出重定向到文件中
追加到文件的操作符
>> 追加标准输出(STDOUT)到文件
2>> 追加标准错误(STDERR)到文件
将标准输出和错误输出定向到不同的位置
COMMAND > /path/to/file.out 2> /path/to/err.out
将标准输出和错误输出进行合并重定向
COMMAND > /path/to/file.out 2>&1
COMMAND >> /path/to/file.out 2>&1
#范例
[root@Centos7 data]# ll /data/ xxx > /data/all.log 2>&1
[root@Centos7 data]# ll
total 4
-rw-r--r--. 1 root root 113 Dec 15 22:56 all.log
[root@Centos7 data]# cat all.log
ls: cannot access xxx: No such file or directory
/data/:
total 4
-rw-r--r--. 1 root root 49 Dec 15 22:56 all.log
合并多个程序
(CMD1;CMD2...)or {CMD1;CMD2;...;} > /path/to/file.out
#范例
[root@Centos7 data]# (ls /data/;date) > /data/lx.txt
[root@Centos7 data]# ll
total 8
-rw-r--r--. 1 root root 113 Dec 15 22:56 all.log
-rw-r--r--. 1 root root 44 Dec 15 22:58 lx.txt
[root@Centos7 data]# cat lx.txt
all.log
lx.txt
Tue Dec 15 22:58:48 CST 2020
/dev/null用法
#/dev/null表示的是一个黑洞,类似于windows中回收站
#可以使用/dev/null来清除一些大文件
[root@Centos7 data]# cat /dev/null > /data/lx.txt
[root@Centos7 data]# cat lx.txt
[root@Centos7 data]#
输出重定向到同一文件中的不同写法
[root@Centos7 data]# ls /data/ /xxx > /data/all.log 2>&1
[root@Centos7 data]# ls /data/ /xxx 2> /data/all.log 1>&2
[root@Centos7 ~]# ls /data/ /xxx &> /data/all.log
#命令从左往右顺序执行下面命令会先输出标准输出在追加至文件
[root@Centos7 ~]# ls /data/ /xxx 2>&1 > /data/all.log
ls: cannot access /xxx: No such file or directory
2.2标准输入重定向
2.2.1 tr命令
tr :翻译,压缩和/或删除标准输入中的字符,
输出至标准输出。
tr [OPTION]... SET1 [SET2]
常用选项
- -d, --delete delete characters in SET1, do not translate
- -s, --squeeze-repeats 把重复的字符用单独一个字符表示,去重
- -t, --truncate-set1 削减 SET1 指定范围,使之与 SET2 设定长度相等
- -c, -C, --complement use the complement of SET1(反选,也就是符合 SET1 的部份不做处理)
\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:]:字母和数字
[:alpha:]: 字母
[:digit:]: 数字
[:lower:]:小写字母
[:upper:]:大写字母
[:space:]:空白字符
[:print:]: 可打印字符
[:punct:]:标点符号
[:graph:]:图形字符
[:cntrl:]: 控制(非打印)字符
[:xdigit:]:十六进制字符
范例
#把/etc/issue中的小写字符都转换成大写字符
[root@Centos7 data]# tr 'a-z' 'A-Z' < issue
[root@Centos7 data]# tr [:lower:] [:upper:] < issue
2.2.2 输入重定向
单行重定向
利用“<” 可以将标准输入重定向
常见的支持输入重定向命令:cat、rm、mail、bc、tr等
#使用输入重定向计算1-10之和
[root@Centos7 data]# seq -s + 1 10 > cal.txt
[root@Centos7 data]# bc < cal.txt
55
多行重定向
使用 "<<终止词" 命令从键盘把多行重导向给STDIN,直到终止词位置之前的所有文本都发送给 STDIN,有时被称为就地文本(here documents)
其中终止词可以是任何一个或多个符号,比如:!,@,$,EOF(End Of File)等,其中EOF 比较常用
范例:
#通过发送邮件测试
#安装邮件服务
[root@centos8 ~]# yum -y install postfix
#启动邮件过程报错
[root@centos8 ~]# systemctl start postfix
Job for postfix.service failed because the control process exited with error code.
See "systemctl status postfix.service" and "journalctl -xe" for details.
#按照要求查看journalctl -xe
fatal: file /etc/postfix/main.cf: parameter mydomain: bad parameter value: 2
#打开配置文件查看如下变量引用了mydomain,却没有声明,推测变量未声明使用变量导致报错
mydestination = $myhostname, localhost.$mydomain, localhost
#将mydomain = domain.tld前注释取消,启动邮件服务成功
[root@centos8 ~]# systemctl start postfix
[root@centos8 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:5355 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 100 127.0.0.1:25 0.0.0.0:*
#使用root用户发送一封邮件给git用户
#可以通过PS2修改输入提示符
[root@centos8 ~]# mail -s test git <<EOF
> hello git
> i am root
> how are you?
> EOF
#通过外部邮件发送
[root@centos8 ~]#yum install mailx -y
3.管道
3.1管道符
“|”:使用该符号来连接多个命令
COMMAND1 | COMMAND2 | COMMAND3
说明
- 将COMMAND1的STDOUT发送给COMMAND2的STDIN
- 所有命令会在当前shell进程中的子shell进程中执行
- 组合多种工具功能
STDERR默认不能通过管道转发,可以利用2>&1或着|&实现
范例
[root@centos8 data]# ls /data/ /err | tr 'a-z' 'A-Z'
ls: cannot access '/err': No such file or directory
/DATA/:
[root@centos8 data]# ls /data/ /err 2>&1 | tr 'a-z' 'A-Z'
LS: CANNOT ACCESS '/ERR': NO SUCH FILE OR DIRECTORY
/DATA/:
3.2 管道中的 - 符号
管道中有时会使用 - 符号
示例: 将 /home 里面的文件打包,但打包的数据不是记录到文件,而是传送到 stdout,经过管道后,将 tar - cvf - /home 传送给后面的 tar -xvf - , 后面的这个 - 则是取前一个命令的 stdout, 因此,就不需要使用 临时file了
tar -cvf - /home | tar -xvf -
3.3 tee命令
tee:重定向到多个目标(read from standard input and write to standard output and files)
tee [OPTION]... [FILE]...
常用选项
- -a 追加
- 用于保存不同阶段的输出,复杂管道的故障排除,同时查看和记录输出
范例
[root@centos8 ~]#cat <<EOF | tee /etc/motd
> welcome
> happy new year
> EOF
welcome
happy new year
练习
1.显示/etc下,以非字母开头,后面跟一个字母及其他任意长度任意字符的文件或目录
[root@centos8 etc]# ls -d /etc/[^[:alpha:]][[:alpha:]]*
/etc/1abcde /etc/1abc.txt
2.复制/etc下所有以P开头,以非数字结尾的文件或目录到/data/mytest1目录中
[root@centos8 etc]# cp -a /etc/p*[^[:digit:]] /data/mytest1/
3.将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out中
[root@centos8 data]# cat /etc/issue | tr 'a-z' 'A-Z' > /data/issue.out
[root@centos8 data]# cat /data/issue.out
\S
KERNEL \R ON AN \M
#使用tee命令
[root@centos8 data]# cat /etc/issue | tr 'a-z' 'A-Z' | tee /data/issue.out
\S
KERNEL \R ON AN \M