标准I/O重定向和管道
1.标准输入和输出
程序:指令+数据
读入数据:Input
输出数据:Output
打开的文件都有一个fd: fifile descriptor (文件描述符)
Linux给程序提供三种 I/O 设备
- 标准输入(STDIN) -0 默认接受来自终端窗口的输入
- 标准输出(STDOUT)-1 默认输出到终端窗口
- 标准错误(STDERR) -2 默认输出到终端窗口
[root@naWang ~]# ll /dev/stdin
lrwxrwxrwx 1 root root 15 11月 23 20:02 /dev/stdin -> /proc/self/fd/0
[root@naWang ~]# ll /dev/stdout
lrwxrwxrwx 1 root root 15 11月 23 20:02 /dev/stdout -> /proc/self/fd/1
[root@naWang ~]# ll /dev/stderr
lrwxrwxrwx 1 root root 15 11月 23 20:02 /dev/stderr -> /proc/self/fd/2
[root@centos8 ~]#ll /dev/std*
lrwxrwxrwx. 1 root root 15 Dec 16 08:56 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 Dec 16 08:56 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 Dec 16 08:56 /dev/stdout -> /proc/self/fd/1
[root@centos8 ~]#ll /proc/self/fd/*
ls: cannot access '/proc/self/fd/255': No such file or directory lrwx------. 1 root root 64 Dec 16 10:59 /proc/self/fd/0 -> /dev/pts/0 lrwx------. 1 root root 64 Dec 16 10:59 /proc/self/fd/1 -> /dev/pts/0
lrwx------. 1 root root 64 Dec 16 10:59 /proc/self/fd/2 -> /dev/pts/0
lr-x------. 1 root root 64 Dec 16 10:59 /proc/self/fd/3 -> /var/lib/sss/mc/passwd
lrwx------. 1 root root 64 Dec 16 10:59 /proc/self/fd/4 -> 'socket:[66542]'
lr-x------. 1 root root 64 Dec 16 10:59 /proc/self/fd/5 -> /var/lib/sss/mc/group
[root@centos8 ~]#ll /proc/`pidof tail`/fd
total 0
lrwx------. 1 root root 64 Dec 16 10:56 0 -> /dev/pts/1
lrwx------. 1 root root 64 Dec 16 10:56 1 -> /dev/pts/1
lrwx------. 1 root root 64 Dec 16 10:56 2 -> /dev/pts/1
lr-x------. 1 root root 64 Dec 16 10:56 3 -> /var/log/messages lr-x------. 1 root root 64 Dec 16 10:56 4 -> anon_inode:inotify
2. I/O重定向redirect
I/O重定向:将默认的输入,输出或错误对应的设备改变,指向新的目标
2.1标准输出和错误重新定向
STDOUT和STDERR可以被重定向到指定文件,而非默认的当前终端
格式
命令 操作符号 文件名
支持的操作符号包括:
- 1> 或 > 把STDOUT重定向到文件
- >| 强制覆盖
- 2> 把STDERR重定向到文件
- &> 把所有输出重定向到文件
以上如果文件已存在,文件内容会被覆盖
set -C 禁止将内容覆盖已有文件,但可追加
set +C 允许覆盖
- >> 可以在原有内容基础上,追加内容
- 把输出和错误重新定向追加到文件
- >> 追加标准输出重定向至文件
- 2>> 追加标准错误重定向至文件
标准输出和错误输出各自定向至不同位置
COMMAND > /path/to/fifile.out 2> /path/to/error.out
合并标准输出和错误输出为同一个数据流进行重定向
&> 覆盖重定向
&>> 追加重定向
COMMAND > /path/to/fifile.out 2>&1 (顺序很重要)
COMMAND >> /path/to/fifile.out 2>&1
[root@naWang ~]# echo 2*3
2*3
[root@naWang ~]# echo 2*3 > bc.log
[root@naWang ~]# cat bc.log
2*3
[root@naWang ~]# bc < bc.log
6
[root@naWang ~]# bc < bc.log > bc2.log
[root@naWang ~]# cat bc2.log
6
标准输入重定向
从文件中导入STDIN,代替当前终端的输入设备,使用 < 来重定向标准输入
某些命令能够接受从文件中导入的STDIN
2.2.1 tr 命令
tr 转换和删除字符
[root@naWang ~]# tr 123 abc
1111
aaaa
^C
[root@naWang ~]# tr 'a-z' 'A-Z'
asdfgh
ASDFGH
^C
[root@naWang ~]# tr -d 'ace'
ace111ace222ace444ace
111222444
^C
tr命令和重定向 :
[root@naWang ~]# more 1.txt
hello hhhjjjakdhdjhsjd
[root@naWang ~]# tr 'a-z' 'A-Z' < 1.txt
HELLO HHHJJJAKDHDJHSJD
tr命令后的选项:
-c –C | 取字符集的补集 |
---|---|
-d | 删除所有属于第一字符集的字符 |
-s | 把连续重复的字符以单独一个字符表示,即去重 |
-t --truncate-set1 | 将第一个字符集对应字符转化为第二字符集对应的字符 |
[:alnum:] | 字母和数字 |
[:alpha:] | 字母 |
[:digit:] | 数字 |
[:lower:] | 小写字母 |
[:upper:] | 大写字母 |
[:space:] | 空白字符 |
[:print:] | 可打印字符 |
[:punct:] | 标点符号 |
[:graph:] | 图形字符 |
[:cntrl:] | 控制(非打印)字符 |
[:xdigit:] | 十六进制字符 |
把多行重定向
使用 “<<终止词” 命令从键盘把多行重导向给STDIN,直到终止词位置之前的所有文本都发送给STDIN,有时被称为就地文本(here documents)
其中终止词可以是任何一个或多个符号,比如:!,@,$,EOF(End Of File),magedu等,其中 EOF 比较常用
[root@naWang ~]# cat > cat.log <<EOF
> 111
> 222
> eof
> EOF
> EOF 0
> EOF
[root@naWang ~]# cat cat.log
111
222
eof
EOF
EOF 0
3 管道
3.1 管道
管道(使用符号“|”表示)用来连接多个命令
格式
命令1 | 命令2 | 命令3|...
功能说明:
- 将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
- 所有命令会在当前shell进程的子shell进程中执行
- 组合多种工具的功能
注意:STDERR默认不能通过管道转发,可利用2>&1 或 |& 实现,格式如下
命令1 2>&1 | 命令2
命令1 |& 命令2
例
[root@centos8 ~]#ls /data /xxx | tr 'a-z' 'A-Z'
ls: cannot access '/xxx': No such file or directory
/DATA:
ALL.LOG
F1.TXT
PASSWD.LOG
STERR.LOG
STOUT.LOG
TEST.LOG
TOUCH.LOG
[root@centos8 ~]#ls /data /xxx 2>&1 | tr 'a-z' 'A-Z'
LS: CANNOT ACCESS '/XXX': NO SUCH FILE OR DIRECTORY
/DATA:
ALL.LOG
F1.TXT
PASSWD.LOG
STERR.LOG
STOUT.LOG
TEST.LOG
TOUCH.LOG
[root@centos8 ~]#ls /data /xxx |& tr 'a-z' 'A-Z'
LS: CANNOT ACCESS '/XXX': NO SUCH FILE OR DIRECTORY
/DATA:
ALL.LOG
F1.TXT
PASSWD.LOG S
TERR.LOG
STOUT.LOG
TEST.LOG
TOUCH.LOG
改密码例子:
[root@naWang ~]# cat p.txt
zaizai
[root@naWang ~]# cat p.txt | passwd --stdin root
更改用户 root 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@naWang ~]# echo zaizai | passwd --stdin root
更改用户 root 的密码 。
passwd:所有的身份验证令牌已经成功更新。
3.2 管道中的 - 符号
管道中有时会使用 - 符号
示例:
将 /home 里面的文件打包,但打包的数据不是记录到文件,而是传送到 stdout,经过管道后,将 tar -cvf - /home 传送给后面的 tar -xvf - , 后面的这个 - 则是取前一个命令的 stdout, 因此,就不需要使用临时fifile了
tar -cvf - /home | tar -xvf -
3.3 tee 命令
利用tee命令可以重定向到多个目标
格式
命令1 | tee [-a ] 文件名 | 命令2
以上可以把命令1的STDOUT保存在文件中,做为命令2的输入
选项:
-a 追加
功能:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出
范例:
[root@centos8 ~]#cat <<EOF | tee /etc/motd
> welcome to magedu
> happy new year
> EOF
welcome to magedu
happy new year
用重定向与管道方法计算1+2+3…+100
[root@naWang ~]# echo {1..100} | tr ' ' + | bc
5050
[root@naWang ~]# echo {1..100..2} | tr ' ' + | bc #奇数相加
2500
[root@naWang ~]# echo {2..100..2} | tr ' ' + | bc #偶数相加
2550
[root@naWang ~]# seq -s + 1 100 |bc
5050
[root@naWang ~]# seq -s + 1 2 100 |bc #奇数相加
2500
[root@naWang ~]# seq -s + 2 2 100 |bc #偶数相加
2550