本章内容
三种I/O设备
把I/O重定向至文件
使用管道
标准输入和输出
程序:指令+数据
读入数据:Input
输出数据:Output
打开的文件都有一个fd: file descriptor (文件描述符)
Linux给程序提供三种I/O设备
标准输入(STDIN)-0 默认接受来自键盘的输入
标准输出(STDOUT)-1 默认输出到终端窗口
标准错误(STDERR)-2 默认输出到终端窗口
I/O重定向:改变默认位置
打开的文件都有一个fd:file description(文件描述符)
[root@centos7 data]#exec 8<>/data/hosts
[root@centos7 data]#ll /proc/$$/fd
total 0
lrwx------. 1 root root 64 Mar 30 14:22 0 -> /dev/pts/3
lrwx------. 1 root root 64 Mar 30 14:22 1 -> /dev/pts/3
lrwx------. 1 root root 64 Mar 30 14:22 2 -> /dev/pts/3
lrwx------. 1 root root 64 Mar 30 16:58 255 -> /dev/pts/3
lrwx------. 1 root root 64 Mar 30 17:17 8 -> /data/hosts
[root@centos7 data]#cat /proc/$$/fd/8
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
其实就是软链接
把输出和错误重新定向到文件
STDOUT和STDERR可以被重定向到文件
命令 操作符号 文件名
支持的操作符号包括:
> 把STDOUT重定向到文件
2> 把STDERR重定向到文件
&> 把所有输出重定向到文件
> 文件内容会被覆盖
set –C 禁止将内容覆盖已有文件,但可追加
>| file 强制覆盖
set +C 允许覆盖
>> 原有内容基础上,追加内容
2> 覆盖重定向错误输出数据流
2>> 追加重定向错误输出数据流
标准输出和错误输出各自定向至不同位置
COMMAND > /path/to/file.out 2> /path/to/error.out
合并标准输出和错误输出为同一个数据流进行重定向
&> 覆盖重定向
&>> 追加重定向
COMMAND > /path/to/file.out 2>&1 (顺序很重要)
COMMAND >> /path/to/file.out 2>&1
():合并多个程序的STDOUT
( cal 2007 ; cal 2008 ) > all.txt
标准输出重定向:>,或者1>
ls > /dev/pts/5
ls > /data/ls.out
对的和错的分别重定向
ls /error /data >>/data/f1 2>>/data/f2
对的和错的放在一起
ls /error /data >all.log 2>&1
注意次序!
新写法:
ls /error /data &>all.log
(ls /error /data 2>&1)>all.log
/dev/null 垃圾箱,无底洞,不希望输出和保存的数据可导到这里
cat 啥都不跟的话会回显,就既有标准输入,又有标准输出
tr命令
tr 转换和删除字符
tr [OPTION]... SET1 [SET2]
选项:
-c -C --complement:取字符集的补集
-d --delete:删除所有属于第一字符集的字符
-s --squeeze-repeats:把连续重复的字符以单独一个字符表示
-t --truncate-set1:将第一个字符集对应字符转化为第二字符集对应的字符
[:alnum:]:字母和数字 [:alpha:]:字母 [:cntrl:]:控制(非打印)字符 [:digit:]:数字 [:graph:]:图形字符 [:lower:]:小写字母 [:print:]:可打印字符 [:punct:]:标点符号 [:space:]:空白字符 [:upper:]:大写字母 [:xdigit:]:十六进制字符
[root@centos7 data]#tr 'a-z' 'A-Z'
asdf1234
ASDF1234
从文件中导入STDIN
使用<来重定向标准输入
某些命令能够接受从文件中导入的STDIN
tr ‘a-z’ ‘A-Z’< /etc/issue
该命令会把/etc/issue中的小写字符都转换成写写字符
tr –d abc < /etc/fstab 删除fstab文件中的所有abc中任意字符
cat > file
mage
wangxiaochun
按ctrl+d离开,可以使用文件来代替键盘的输入
Cat > filea < fileb
[root@centos7 ~]#tr 'a-z' 'A-Z' < anaconda-ks.cfg > /data/log
[root@centos7 ~]#cat /data/log
[root@centos7 doc]#tr -dc 'abc'
23423aabc3sff
aabc
[root@centos7 doc]#tr -s "abc"
aaabbbacde
abacde
[root@centos7 data]#cat win3.txt
a b c
[root@centos7 data]#tr -s ' ' <win3.txt
a b c
[root@centos7 data]#df > df.log
[root@centos7 data]#tr -s ' ' : < df.log
Filesystem:1K-blocks:Used:Available:Use%:Mounted:on
/dev/sda2:51474912:3405572:45431516:7%:/
devtmpfs:523248:0:523248:0%:/dev
tmpfs:537748:0:537748:0%:/dev/shm
tmpfs:537748:14544:523204:3%:/run
tmpfs:537748:0:537748:0%:/sys/fs/cgroup
/dev/sda1:999320:130824:799684:15%:/boot
/dev/sda3:20511312:45420:19400932:1%:/data
tmpfs:107552:12:107540:1%:/run/user/42
tmpfs:107552:0:107552:0%:/run/user/0
/dev/sr0:8490330:8490330:0:100%:/mnt
[root@centos7 qjy]#echo abcdef | tr 'abcd' 'xyz'
xyzzef
[root@centos7 qjy]#echo abcdef | tr -t 'abcd' 'xyz'
xyzdef
把多行发送给STDIN
使用“<<终止词”命令从键盘把多行重导向给STDIN
直到 终止词 位置的所有文本都发送给STDIN
有时被称为就地文本(heretext)
mail -s "Please Call" admin@magedu.com <<END
> Hi Wang,
>
> Please give me a call when you get in. We may need
> to do some maintenance on server1.
>
> Details when you're on-site
> Zhang
> END
mail [-s] "hello" qjy@magedu.com < mail.txt
邮件里可用命令,如`hostname`
管道
管道(使用符号“|”表示)用来连接命令
命令1 | 命令2 | 命令3 | …
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
STDERR默认不能通过管道转发,可利用2>&1 或 |& 实现
最后一个命令会在当前shell进程的子shell进程中执行用来
组合多种工具的功能
ls | tr ‘a-z’ ‘A-Z’
cat mail.txt | mail -s 'hello' root
ls /boot /error 2>&1 | tr 'a-z' 'A-Z'
或新写法:
ls /boot /error |& tr 'a-z' 'A-Z
比较老的系统如RHEL 5.4等可能不支持'
less :一页一页地查看输入
ls -l /etc | less
mail:通过电子邮件发送输入
echo "test email" | mail -s "test" user@example.com
lpr:把输入发送给打印机
echo "test print" | lpr -P printer_name
管道中-符号
示例:
将/home里面的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将tar -cvf - /home传送给后面的tar -xvf - ,后面的这个 - 则是取前一个命令的 stdout,因此,就不需要使用临时file了
tar -cvf - /home | tar -xvf -
重定向到多个目标(tee)
命令1 | tee [-a ] 文件名 | 命令2
把命令1的STDOUT保存在文件中,做为命令2的输入
-a 追加
使用:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出
练习:
1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
[root@centos7 ~]#cat /etc/issue | tr [[:lower:]] [[:upper:]] > /tmp/issue.out
2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中
[root@centos7 ~]#who | tr [[:lower:]] [[:upper:]]
3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:
Hello, I am 用户名,The system version is here,please help me to check it ,thanks!
操作系统版本信息
[qjy@centos7 ~]$mail -s "help" root <<EOF
Hello, I am `whoami`, The system version is here, please help me to check it, thanks!
`cat /etc/redhat-release`
EOF
4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开
[root@centos7 ~]#ls /root | tr '\n' ' '
5、计算1+2+3+..+99+100的总和
echo {1..100} | tr ' ' + | bc
seq -s + 100 | bc
也可用循环
6、删除Windows文本文件中的‘^M’字符
[root@centos7 data]#hexdump -C win.txt
00000000 61 0d 0a 62 0d 0a 63 |a..b..c|
00000007
[root@centos7 data]#tr -d '\15' < win.txt >win2.txt
[root@centos7 data]#hexdump -C win2.txt
00000000 61 0a 62 0a 63 |a.b.c|
00000005
[root@centos7 data]#tr -d '\r' < win.txt >win3.txt
[root@centos7 data]#hexdump -C win3.txt
00000000 61 0a 62 0a 63 |a.b.c|
00000005
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 'a-z '
8、将PATH变量每个目录显示在独立的一行
答:echo $PATH | tr : '\n'
9、将指定文件中0-9分别替代成a-j
答:tr '0-9' 'a-j' < a.txt > a.txt
10、将文件/etc/centos-release中每个单词(由字母组成)显示在独立的一行,并无空行
答:[root@centos7 ~]#cat /etc/centos-release | tr -dc '[:alpha:] ' | tr -s ' ' '\n'
CentOS
Linux
release
Core
例:创建随机小写字母文件名
[root@centos7 data]#touch `openssl rand -base64 12 | tr -dc '[:lower:]'`
思考:
以下4项哪一项是与众不同的?
A cmd > log 2>&1
B cmd 2>&1 > log
C cmd &> log
D cmd 2>log >&2
答案:B