Linux输入输出

发布时间 2023-12-25 12:17:13作者: coder雪山

1.重定向概述

1.什么是重定向

将原本要输出到屏幕的数据信息,重新定向到某个指定的文件中。比如:每天凌晨定时备份数据,希望将备份数据的结果保存到某个文件中。

这样第二天通过查看文件的内容就知道昨天备份的数据是成功还是失败。

2.为何要使用重定向

1.当屏幕输出的信息很重要,而且希望保存重要的信息时;

2.后台执行中的程序,不希望他干扰屏幕正常的输出结果时;

3.系统的例行命令, 例如定时任务的执行结果,希望可以存下来时;

4.一些执行命令,我们已经知道他可能出现错误信息, 想将他直接丢弃时;

5.错误日志与正确日志需要分别输出至不同的文件保存时;

3.学习重定向的预备知识,标准输入与输出

当运行一个程序时通常会自动打开三个标准文件,分别是标准输入、标准输出、错误输出

   
名称 文件描述符 作用
标准输入(STDIN) 0 默认是键盘,也可以是文件或其他命令的输出。
标准输出(STDOUT) 1 默认输出到屏幕。
错误输出(STDERR) 2 默认输出到屏幕。
文件名称(filename) 3+  

输入和输出

  • 标准输入 默认是来自键盘的输入 stdin 0

  • 标准输出 默认输出到终端窗口 stdout 1

  • 标准错误输出 默认输出到终端窗口 stderr 2

2.I/O重定向

改变输出另外的地方,比如重定向输出到终端,改到输出到文件

m[root@192 test]#file /run/gssproxy.sock > c
m[root@192 test]#cat c
/run/gssproxy.sock: socket

错误输出到文件f中

m[root@192 test]#ls sdjfjei 2> f
m[root@192 test]#cat f
ls: cannot access sdjfjei: No such file or directory

> 覆盖

  • > 将标准输出重定向到文件中

  • 2> 将错误输出重定向到文件中

  • &> 将所有的输出都重定向到文件中

禁止、允许覆盖

m[root@192 test]#>q
m[root@192 test]#ls jdjfdk 2>q
m[root@192 test]#set -C
m[root@192 test]#>q
-bash: q: cannot overwrite existing file
  • 禁止覆盖 set -C

  • 允许覆盖 set +C

>> 追加

m[root@192 test]#ls djfjdkf 2>>a
m[root@192 test]#ls djfjdkf 2>>a
m[root@192 test]#ls djfjdkf 2>>a
m[root@192 test]#cat a
ls: cannot access djfjdkf: No such file or directory
ls: cannot access djfjdkf: No such file or directory
ls: cannot access djfjdkf: No such file or directory

>> 将标准输出追加到文件中

2>> 将错误输出追加到文件中

&>> 将所有输出追加到文件中

标准输入和错误输入分开保存

[root@localhost ~]#ls f 45yuio > log.log 2> error.log
[root@localhost ~]#cat log.log 
f
[root@localhost ~]#cat error.log 
ls: cannot access 45yuio: No such file or directory

合并所有的输出

  • &> 覆盖重定向

  • &>> 追加重定向

  • command > file 2>&1

  • command >> file 2>&1

# 把错误的也合并到标准输出到r文件
m[root@192 test]#ls f 34jdj > r 2>&1
m[root@192 test]#cat r
ls: cannot access 34jdj: No such file or directory
f
  • ():合并多个文件的输出

m[root@192 test]#(ls djfj;ls djfjjjnf) 2>g
m[root@192 test]#cat g
ls: cannot access djfj: No such file or directory
ls: cannot access djfjjjnf: No such file or directory
  • /dev/null 黑洞,不断地吞

超级回收站,不断地接受输出

m[root@192 test]#(ls f;ls djfjdk) &> /dev/null
  • /dev/zero 不断地吐

# 测试磁盘速度
m[root@192 test]#dd if=/dev/zero of=j bs=100M count=2
2+0 records in
2+0 records out
209715200 bytes (210 MB) copied, 0.247444 s, 848 MB/s

3.从文件导入stdin

tr 字符替换

-t 截断
-d 删除
-s 压缩,去重
-c 取反

# 从文件中替换
[root@localhost ~]#tr 'a-z' 'A-Z' < /etc/issue
\S
KERNEL \R ON AN \M
[root@localhost ~]#tr 'a-z' 'A-Z' 
qwertyy
QWERTYY
12345678
12345678
ASDFGHJ
ASDFGHJ
qwertyuio
QWERTYUIO
^C
[root@localhost ~]#tr ab 12
ab
12
abb
122
asdfghjkl
1sdfghjkl
^C
[root@localhost ~]#tr abc 12
ab
12
abc
122
abc
122
^C
[root@localhost ~]#tr ab 123
ab
12
abb
122
avc
1vc
qbc
q2c
abc
12c

# 截断 
[root@localhost ~]#tr -t abc 12
abc
12c
ab
12

# 删除
[root@localhost ~]#tr -d abc
qwertyui
qwertyui
an^H^H
n

abc

artyibrtyuiocrtyuiop
rtyirtyuiortyuiop
^C
[root@localhost ~]#tr -d abc < /etc/issue
\S
Kernel \r on n \m

[root@localhost ~]#cat /etc/issue
\S
Kernel \r on an \m
[root@localhost ~]#tr -s a
abc
abc
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabc
abc
^C
[root@localhost ~]#tr -sc a 
aasdaaaaaaa
aasdaaaaaaa
^[[A^H^H^C
[root@localhost ~]#tr -sc a 
aaaaaaaaabbbbbbbbbbbbbccccccccddddddddddd
aaaaaaaaabcd
[root@localhost ~]#tr -dc a
aaaaaaaaaaaabbbbbbbbbb
asdfghjkqwertyuiozxcvbnmxcvbnm,.
aaaaaaaaaaaaa
ctrl+d 结束
[root@localhost ~]#tr -dc "a\n"
asdfghjk
a
wertyujk;l'



asdfghj
a
[root@localhost test]#tr -d a < issue > issue  
# 处理完成以后不能写会到源文件,要写到新的文件中


[root@localhost test]#seq 1 10 > b
[root@localhost test]#cat b
1
2
3
4
5
6
7
8
9
10
[root@localhost test]#tr -d "\n" < b
12345678910[root@localhost test]#tr -d "\n" < b
[root@localhost test]#tr "\n" " " <b
1 2 3 4 5 6 7 8 9 10 [root@localhost test]#tr "\n" " " <b >c
[root@localhost test]#cat c
1 2 3 4 5 6 7 8 9 10 [root@localhost test]#tr " " "\n" <c
1
2
3
4
5
6
7
8
9
10

多行发送给stdin

# 第一种方式
[root@localhost test]#cat > f1
qwert
wertyui
wertyui
wertyuiopasdfghjk
sdfghjkl
sdfyhjkl;sdfghjkl;xcvb

# 第二种方式
[root@localhost test]#cat > f2 <<EOF
> qwerty
> qwertyu
> wertyui
> qwertyu
> EOF
EOF 不是必须得,只要两个相同就可以

4.管道

管道使用“|”来表示,主要用来连接左右两个命令, 将左侧的命令的标准输出, 交给右侧命令的标准输入

PS: 无法传递标准错误输出至后者命令

命令1|命令2|命令3

  • 把命令1的输出结果当做命令2的输入结果,把命令2的输出结果当成命令3的输入结果

  • 默认情况下,管道只能传送标准输出

  • 如果需要把错误输出也传递,则需要|&

  • 一般用来组合多个命令

  • 有一些命令是不接受管道的

[root@localhost test]#ls f1|tr 'a-z' 'A-Z'
F1
[root@localhost test]#ls f
ls: cannot access f: No such file or directory
[root@localhost test]#ls f|tr 'a-z' 'A-Z'
ls: cannot access f: No such file or directory
[root@localhost test]#ls f|&tr 'a-z' 'A-Z'
LS: CANNOT ACCESS F: NO SUCH FILE OR DIRECTORY
# 不接受管道
[root@localhost test]#echo file{1..20}|touch 
touch: missing file operand
Try 'touch --help' for more information.

案例1: 将/etc/passwd 中的用户按 UID 大小排序

[root@lqz ~]# sort -t":" -k3 -n /etc/passwd
[root@lqz ~]# sort -t":" -k3 -n /etc/passwd -r
[root@lqz ~]# sort -t":" -k3 -n /etc/passwd |head

案例2: 统计当前/etc/passwd 中用户使用的 shell 类型

#思路:取出第七列(shell) | 排序(把相同归类)| 去重
[root@lqz ~]# awk -F: '{print $7}' /etc/passwd
[root@lqz ~]# awk -F: '{print $7}' /etc/passwd |sort
[root@lqz ~]# awk -F: '{print $7}' /etc/passwd |sort |uniq
[root@lqz ~]# awk -F: '{print $7}' /etc/passwd |sort |uniq -c

案例4: 统计网站的访问情况 top 20

#思路: 打印所有访问的连接 | 过滤访问网站的连接 | 打印用户的 IP | 排序 | 去重

[root@lqz ~]# yum -y install httpd
[root@lqz ~]# systemctl start httpd
[root@lqz ~]# systemctl stop firewalld

[root@lqz ~]# ss -an |grep :80 |awk -F":" '{print $8}' |sort |uniq -c
[root@lqz ~]# ss -an |grep :80 |awk -F":" '{print $8}' |sort |uniq -c |sort -k1 -rn |head -n 20

案例5: 打印当前所有 IP

[root@lqz ~]# ip addr |grep 'inet ' |awk '{print $2}' |awk -F"/" '{print $1}'
127.0.0.1
192.168.69.112

案例6: 打印根分区已用空间的百分比(仅打印数字)

[root@lqz ~]# df |grep '/$' |awk '{print $5}' |awk -F"%" '{print $1}'

PS: 管道命令符能让大家能进一步掌握命令之间的搭配使用方法,进一步提高命令输出值的处理效率。

1.管道中的tee技术

#选项: -a追加
[root@lqz ~]# ip addr |grep 'inet ' |tee ip.txt |awk -F"/" '{print $1}' |awk '{print $2}'
127.0.0.1
10.0.0.100

[root@lqz ~]# cat ip.txt
inet 127.0.0.1/8 scope host lo
inet 10.0.0.100/24 brd 192.168.69.255 scope global ens32

重定向与 tee 有他们在使用过程中有什么区别

[root@lqz ~]# date > date.txt    #直接将内容写入date.txt文件中
[root@lqz ~]# date |tee date.txt #命令执行会输出至屏幕,但会同时保存一份至date.txt文件中

2.xargs参数传递,主要让一些不支持管道的命令可以使用管道技术

# which cat|xargs ls- l
# ls |xargs rm -fv
# ls |xargs cp -rvt /tmp/ -或-> ls | xargs -I {} cp -rv {} /tmp/
# ls |xargs mv -t /tmp/   -或-> ls | xargs -I {}  mv {} /tmp