2023.6.2 Linux重定向与管道

发布时间 2023-06-02 01:59:04作者: 必兮相语--

02.Linux重定向与管道
1.1标准输⼊与输出
1.2输出重定向
1.3输⼊重定向
1.4进程管道技术
1.4.1tee管道技术
1.4.2参数传递xargs
Author vx: WingspanGo
为何要使⽤重定向
1.当屏幕输出的信息很重要,⽽且希望保存重要的信息时;
2.后台执⾏中的程序,不希望他⼲扰屏幕正常的输出结果时;
3.系统的例⾏命令, 例如定时任务的执⾏结果,希望他可以存下来时;
4.⼀些执⾏命令,我们已经知道他可能出现错误信息, 想将他直接丢弃时;
5.错误⽇志与标准正确⽇志需要分别输出⾄不同的⽂件;
1.1标准输⼊与输出
执⾏⼀个 shell 程序时通常会⾃动打开三个标准⽂件
标准输⼊(STDIN,⽂件描述符为0):通常对应终端的键盘,也可从其他⽂件或命令或者⽂件内容中输⼊。
标准输出(STDOUT,⽂件描述符为1):默认输出到屏幕。
错误输出(STDERR,⽂件描述符为2):默认输出到屏幕。
⽂件名称(filename,⽂件描述符为3+)
进程将从标准输⼊中得到数据,将正常输出打印⾄屏幕终端,将错误的输出信息也打印⾄屏幕终端。
进程使⽤⽂件描述符 (file descriptors) 来管理打开的⽂件

 

 

以 cat 命令为例, cat 命令的功能是从命令⾏给出的⽂件中读取数据,并将这些数据直接送到标准输出。若使⽤如
下命令:
[root@wing ~]# cat /etc/passwd

将会把⽂件 /etc/passwd 的内容依次显示到屏幕上。但如果 cat 命令⾏中没有参数, 它就会从标准输⼊中读取数
据, 并将其送到标准输出。
输⼊输出过程检测
1.2输出重定向
重定向: 改变标准输⼊、标准输出的⽅向的就是重定向
标准覆盖输出重定向 >
标准追加输出重定向 >>
错误覆盖输出重定向 2>
错误追加输出重定向 2>>
输⼊重定向 <
[root@wing ~]# cat
hello
hello
^C
//⽤户输⼊的每⼀⾏都⽴刻被cat命令输出到屏幕上。
//持续追踪查看⽂件内容
[root@wing ~]# tail -f /root/command/std/test.log
ctrl+z 将进程转到后台
ctrl+z 将进程转到后台
//查看运⾏的进程
[root@wing ~]# ps
PID TTY     TIME CMD
5848 pts/1  00:00:00 bash
6885 pts/1  00:00:00 tail
6888 pts/1  00:00:00 ps
//查看6885进程下的⽂件描述符
[root@wing ~]# ls -l /proc/6885/fd
total 0
lrwx------ 1 root root 64 Dec 3 06:57 0 -> /dev/pts/1
lrwx------ 1 root root 64 Dec 3 06:57 1 -> /dev/pts/1
lrwx------ 1 root root 64 Dec 3 06:56 2 -> /dev/pts/1
lr-x------ 1 root root 64 Dec 3 06:57 3 -> /etc/passwd
lr-x------ 1 root root 64 Dec 3 06:57 4 -> inotify
//Linux查看标准输⼊输出设备
[root@wing ~]# ls -l /dev/std*
lrwxrwxrwx 1 root root 15 Dec 2 22:30 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Dec 2 22:30 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Dec 2 22:30 /dev/stdout -> /proc/self/fd/1

1.2输出重定向
重定向: 改变标准输⼊、标准输出的⽅向的就是重定向
标准覆盖输出重定向 >
标准追加输出重定向 >>
错误覆盖输出重定向 2>
错误追加输出重定向 2>>
输⼊重定向 <

类型 操作符 ⽤途
标准覆盖输出重定向 > 将命令的执⾏结果输出到指定的⽂件中, ⽽不是直接显示在屏幕上
标准追加输出重定向 >> 将命令执⾏的结果追加输出到指定⽂件
标准输⼊重定向 << 将命令中接收输⼊的途径由默认的键盘更改为指定的⽂件

案例1: 标准输出重定向(覆盖)

 

//标准输出重定向, 先清空,后写⼊, 如果⽂件不存在则创建
[root@wing ~]# ifconfig ens33 > abc

案例2: 标准输出重定向(追加)

 

//标准追加输出重定向, 向配置⽂件末尾追加内容
[wing@wing ~]$ echo "This is network conf" >> if

案例3: 错误输出重定向

 

//正确输出以及错误输出重定向⾄⼀个⽂件
[root@wing ~]# useradd test
[root@wing ~]# su - test
//将标准输出和标准错误输出重定向到不同⽂件
[wing@wing ~]$ find /etc -name "*.conf" 1>a 2>b

 

案例4: 正确和错误都输⼊到相同位置

 

//将标准输出和标准错误输出重定向到同⼀个⽂件, 混合输出
[wing@wing ~]$ find /etc -name "*.conf" &>ab
//合并两个⽂件内容⾄⼀个⽂件
[wing@wing ~]$ cat a b > c

案例5: 正确和错误都输⼊到相同位置

 

//重定向到相同的位置
[root@wing ~]# ls /root /error >ab 2>&1

案例6: 重定向到空设备/dev/null

 

 

//空设备,即将产⽣的输出丢掉
[root@wing ~]# ls /root /error >ab 2>/dev/null
[root@wing ~]# ls /root /error >ab &>/dev/null
//思考
[root@wing ~]# cp /etc/passwd /dev/null
[root@wing ~]# cp /etc/passwd /etc/passwd1 2>/dev/null
如果/dev/null 设备被删除
[root@wing ~]# rm -f /dev/null
//1.⼿动创建
[root@wing ~]# mknod -m 666 /dev/null c 1 3
//2.重启⾃动创建
MAJOR主设备号 MINOR从设备号
主设备号相同: 表示为同⼀种设备类型,也可以认为 kernel 使⽤的是相同的驱动
从设备号:在同⼀类型设备中的⼀个序号

 

案例7: 脚本中使⽤重定向

[root@wing ~]# vim ping.sh
ping -c1 192.168.9.3
if [ $? -eq 0 ];then
 echo "192.168.9.3 is up."
else
 echo "192.168.9.3 is down."
fi
[root@wing ~]# chmod +x ping.sh
[root@wing ~]# ./ping.sh
//改进后版
[root@wing ~]# vim ping.sh
ping -c1 192.168.9.3 &>/dev/null
if [ $? -eq 0 ];then

echo "192.168.9.3 is up."
else
 echo "192.168.9.3 is down."
fi

 

案例8: 脚本中使⽤重定向

 

[root@wing ~]# vim ping2.sh
ping -c1 192.168.9.3 &>/dev/null
if [ $? -eq 0 ];then
 echo "192.168.9.3 is up." >>up.txt
else
 echo "192.168.9.3 is down." >>down.txt
fi
[root@wing ~]# chmod +x ping2.sh
[root@wing ~]# ./ping2.sh

1.3输⼊重定向

标准输⼊: < 等价 0<

案例1

[root@wing std]# sort < 1.txt
1
10
2
3
4
5
6
7
8
9
[root@wing std]# sort -rn < 1.txt
10
9
8
7
6
5
4
3
2
1

案例2

////没有改变输⼊的⽅向,默认键盘,此时等待输⼊
[root@wing ~]# grep 'root'
xxx
xxx
[root@wing ~]# grep 'root' < /etc/passwd
root:x:0:0:root:/root:/bin/bash

案例3

[root@wing ~]# dd if=/dev/zero of=/file1.txt bs=1M count=20
[root@wing ~]# dd </dev/zero >/file2.txt bs=1M count=20
fio 磁盘读写性能测试

案例4

//mysql 表结构导⼊
[root@wing ~]# mysql -uroot -p123 < bbs.sql

案例5: 利⽤重定向建⽴多⾏的⽂件

//⼿动执⾏ shell 命令
[root@wing ~]# echo "111" > file1.txt
[root@wing ~]# cat file1.txt
111
[root@wing ~]# cat >file2.txt
111
222
333
^D
[root@wing ~]# cat >>file3.txt
aaa
bbb
ccc
^D

 

案例6: 利⽤重定向建⽴多⾏的⽂件

//脚本 script 创建多⾏⽂件
[root@wing ~]# vim create_file.sh
cat >file200.txt <<EOF
111
222
333
yyy

ccc
EOF
[root@wing ~]# vim vm.sh
cat <<-EOF
+------------------- --- ---- --- ---- --- --- ---- --- --+ ||
| ====================== |
| 虚拟机基本管理 v5.0 |
| by wing |
| ====================== |
| 1. 安装 KVM |
| 2. 安装或重置 CentOS-6.9 |
| 3. 安装或重置 CentOS-7.4 |
| 5. 安装或重置 Windows-7 |
| 6. 删除所有虚拟机 |
| q. 退出管理程序 |
+------------------- --- ---- --- ---- --- --- ---- --- --+
EOF

案例7: 两条命令同时重定向

[root@wing ~]# ls; date &>/dev/null
[root@wing ~]# ls &>/dev/null; date &>/dev/null
[root@wing ~]# (ls; date) &>/dev/null

扩展点: subshell

[root@wing ~]# cd /boot; ls
//subshell 中执⾏
[root@wing ~]# (cd /boot; ls)
//如果不希望某些命令的执⾏对当前 shell 环境产⽣影响,请在subshell中执⾏

1.4进程管道技术

管道操作符号 "|" 连接左右两个命令, 将左侧的命令的标准输出, 交给右侧命令的标准输⼊

 

 下⾯的命令将 ls 命令的输出传递给 grep 命令来搜索包含 txt 的⽂件名:

ls | grep txt

管道操作符可以连接任意数量的命令,例如:

command1 | command2 | command3 | ... | commandN

格式: cmd1 | cmd2 [...|cmdn]

案例1: 将/etc/passwd 中的⽤户按 UID ⼤⼩排序

[root@wing ~]# sort -t":" -k3 -n /etc/passwd
[root@wing ~]# sort -t":" -k3 -n /etc/passwd -r
[root@wing ~]# sort -t":" -k3 -n /etc/passwd |head
sort -t":" -k3 -n /etc/passwd | head -n 10 | tail -n 1

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

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

案例3: 统计出最占CPU的5个进程

[root@wing ~]# ps aux --sort=-%cpu |head -6

进程资源 cpu mem
pid
user

time

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

//思路: 打印所有访问的连接 | 过滤访问⽹站的连接 | 打印⽤户的 IP | 排序 | 去重
www.xxx.com/v1/api/add 假如说这个接⼝访问量⼤,⾃⼰模拟 找出来访问⽹站⽐较⾼的请求api
[root@wing ~]# yum -y install nginx
[root@wing ~]# systemctl start nginx
[root@wing ~]# systemctl stop firewalld
[root@wing ~]# netstat -antup |egrep :80 |egrep ESTAB |sort |uniq -c
[root@wing ~]# netstat -antup |egrep :80 |egrep ESTAB |sort |uniq -c |sort -k1 -rn
|head -n 20

 

案例5: 打印当前所有 IP

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

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

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

1.4.1tee管道技术

 

[root@wing ~]# ip addr |grep 'inet ' |tee ip.txt |awk -F"/" '{print $1}' |awk '{print
$2}'
127.0.0.1
192.168.69.112
192.168.122.1
[root@wing command]# cat ip.txt
 inet 127.0.0.1/8 scope host lo
 inet 192.168.9.3/24 brd 192.168.9.255 scope global noprefixroute ens33

重定向与 tee 区别

[root@wing ~]# date > date.txt
[root@wing ~]# date |tee date.txt

1.4.2参数传递xargs

将参数列表转换成⼩块分段传递给其他命令
读⼊ stdin 的数据转换为参数添加⾄命令后⾯
让⼀些不⽀持管道的命令可以使⽤管道。

管道命令符能让⼤家能进⼀步掌握命令之间的搭配使⽤⽅法,进⼀步提⾼命令输出值的处理效率。

[root@wing ~]# grep "/sbin/nologin" /etc/passwd | wc -l
33
[root@wing ~]# head -5 /etc/passwd|tail -1
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
//使⽤grep过滤输出信息
[root@wing ~]# ls -l /etc |grep pass
-rw-r--r--  1 root root  4653 Dec 2 15:54 passwd
-rw-r--r--. 1 root root  4606 Dec 2 15:54 passwd-
-rw-r--r--. 1 root root  1454 Sep 23 2014 passwd.OLD
//管道和标准输出以及标准错误输出, 使⽤普通⽤户执⾏如下命令
find /etc/ -name "p*"|grep passwd
find /etc/ -name "p*"|grep passwd > a
find /etc/ -name "p*"|grep passwd > b
find /etc/ -name "p*"|grep passwd &> ab

注意事项:
1.在管道后⾯的命令,都不应该在写⽂件名
2.在管道中只有标准输出才可以传递下⼀个命令, 标准错误输出会直接输出终端显示, 建议在使⽤管道前将标
准错误输出重定向。
例如: find /etc -name "*.conf" 2>/dev/null | grep rc
3.有些命令不⽀持管道技术, 但是可以通过 xargs 来实现管道传递。

例如: which cat|xargs ls -l
例如: ls |xargs rm -rvf
例如: ls |xargs cp -rvft /tmp/ -> ls | xargs -I {} cp -rvf {} /tmp
例如: ls |xargs mv -t /tmp/ -> ls | xargs -I {} mv {} /tmp