Linux重定向

重定向概述:

什么是重定向:

Linux中的重定向就是将原本要输出到屏幕中的数据信息,重新指向某个特定文件当中,或者定向到黑洞文件(/dev/null)中。

重定向的作用:

  1. 当屏幕输出的信息很重要,希望保存时
  2. 后台执行的程序一般都会有输出,不希望它输出干扰到终端
  3. 执行定时备份任务,希望将备份结果保留下来时
  4. 执行一些命令,会提示一些报错信息,可以直接将报错丢弃。
  5. 执行命令时希望将报错和正确内容区分在不同文件中时(日志)

命令返回值(拓展)

在Linux下,不管是启动桌面程序还是执行命令,所有程序在结束时都会返回一个数字值,这个值叫做返回值,或者称为错误号。

[root@localhost ~]# ls
[root@localhost ~]# echo $?
0

我们执行ls命令,通过echo$?,打印$?的值,我们发现返回值是0

返回值是0,则代表上一条命令执行成功返回值
非0,则代表上一条命令执行不成功

文件描述符

li可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。 用户可以自定义文件描述符范围是:3-num,这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。

linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2。以后打开文件后。新增文件绑定描述符可以依次增加。 一条shell命令执行,都会继承父进程的文件描述符。因此,所有运行的shell命令,都会有默认3个文件描述符。

名称 文件描述符 作用
标准输入(stdin) 0 通常是键盘,也可以是其他文件或者命令的输出的内容可以作为标准输入
标准输出(stdout) 1 默认输出到屏幕
错误输出(stderr) 2 默认输出到屏幕
文件名称(filename) 3+
  • 当进程操作一个文件时:

    1. 首先程序是无法直接访问硬件,需要借助内核来访问文件
    2. 而内核kernel需要利用文件描述(file descriptor)来访问
  • 总结:进程使用文件描述符来管理打开的文件对应关系

  • 通常程序访问一个文件至少会打开三个标准文件,分别是标准输入,标准输出,错误输出

  • 进程将从标准输入中的到数据,将正常输出打印至屏幕终端,将错误的输出信息也打印至屏幕终端

输入输出符号及作用

名称 符号 作用
标准输入重定向 <或者0< 将符号右边的内容交给符号左边的命令
标准输出覆盖重定向 >或者1> 将原本要输出在屏幕上的正确内容,覆盖到重定向的文件中
标准输出追加重定向 >>或者1>> 将原本要输出在屏幕上的正确内容,追加到重定向的文件中
错误输出覆盖重定向 2> 将原本要输出在屏幕上的错误内容,覆盖到重定向的文件中
错误输出追加重定向 2>> 将原本要输出在屏幕上的错误内容,追加到重定向的文件中

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

  • 标准输出重定向示例
    1. 如果文件不存在则创建
    2. 如果文件存在则清空内容,后写入
[root@localhost ~]# ifconfig eth0 > abc

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

  • 标准输出重定向示例
    1. 如果文件不存在则创建
    2. 如果文件存在则在文件尾部添加内容
[root@localhost ~]# echo "This is network conf" >> if 

案例3:错误输出重定向

  • 错误输出重定向示例
    1. 正确输出及错误输出至相同文件
    2. 正确输出及错误输出至不同的文件

[root@localhost ~]#find /etc -name "*.conf" 1>ok 2>error

案例4:混合和输出重定向

  • 错误输出重定向示例
    1. 将正确输出和错误输出混合至同一文件
    2. 将两个文件内容组合为一个文件
#将标准输出和标准错误输出重定向到同一个文件, 混合输出
1.[root@localhost ~]# find /etc -name "*.conf" &>ab
2.[root@localhost ~]# find /etc -name "*.conf" >ab 2>&1

#合并两个文件内容至一个文件
[root@localhost ~]# cat a b > c

案例5:将内容输出至黑洞

[root@localhost ~]# ls /root/error>ab 2>/dev/null

[root@localhost ~]# ls /root/error>ab &>/dev/null

案例6:输入重定向

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

2.
[root@localhost ~]# dd if=/dev/zero of=/file1.txt bs=1M count=20
[root@localhost ~]# dd </dev/zero >/file2.txt bs=1M count=20

案例7:利用重定向建立多行的文件

[root@localhost ~]# vim fruit.sh
#!/bin/sh
menu(){
      cat <<EOF
    +------------+
    | 1 | apple  |
    +---+--------+
    | 2 | pear   |
    +---+--------+
    | 3 | banana |
    +---+--------+
    | 4 | cherry |
    +---+--------+
EOF
read -p "please input a num: " fruit
}

usage(){
     echo "USAGE:请输入水果编号"
     exit 1
}

color(){
case "$fruit" in
  1)
    echo -e "\E[1;31mapple \E[0m"
    ;;
  2)
    echo -e "\E[1;20mpear \E[0m"
    ;;
  3)
    echo -e "\E[1;33mbanana \E[0m"
    ;;
  4)
    echo -e "\E[1;35mcherry \E[0m"
    ;;
  *)
    usage
esac
}
menu
color

输入输出过程检测

#持续追踪查看文件内容
[root@localhost ~]# tail -f /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
lw:x:1000:1000::/home/lw:/bin/bash
lw1:x:1001:1001::/home/lw1:/bin/bash
oldboy:x:615:1002::/home/oldboy:/bin/bash
^Z  (ctrl+z 将进程转到后台)
[1]+  Stopped                 tail -f /etc/passwd

#查看运行的进程
[root@localhost ~]# ps
   PID TTY          TIME CMD
  8217 pts/1    00:00:00 bash
  8258 pts/1    00:00:00 tail
  8259 pts/1    00:00:00 ps

#查看8258进程下的文件描述符
[root@localhost ~]# ls -l /proc/8258/fd
total 0
lrwx------. 1 root root 64 Apr 13 19:25 0 -> /dev/pts/1
lrwx------. 1 root root 64 Apr 13 19:25 1 -> /dev/pts/1
lrwx------. 1 root root 64 Apr 13 19:25 2 -> /dev/pts/1
lr-x------. 1 root root 64 Apr 13 19:25 3 -> /etc/passwd
lr-x------. 1 root root 64 Apr 13 19:25 4 -> anon_inode:inotify

# Linux查看标准输入输出设备
[root@localhost ~]# 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

补充:Linux重定向&符

$ command > file 2>&1
$ command >> file 2>&1

这里的&没有固定的意思

放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符

换言之 2>1 代表将stderr重定向到当前路径下文件名为1regular file中,而2>&1代表将stderr重定向到文件描述符1的文件(即/dev/stdout)中,这个文件就是stdoutfile system中的映射

&>file是一种特殊的用法,也可以写成>&file,二者的意思完全相同,都等价于

>file 2>&1

进程管道技术

什么是管道

  • 管道操作符“ | ”,主要用来连接左右两个命令,将左侧的命令的标准输出,交给右侧命令的标准输入
  • 注意事项:无法传递标准错误输出至后者命令

格式

cmd1 | cmd2 […| cmdn]

管道使用范例

范例1

将/etc/passwd中的UID大小排序

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

范例2

打印当前所有IP

[root@localhost ~]# ip ad | grep "inet " | awk '{print $2}'|awk -F "/" '{print $1}'
127.0.0.1
10.0.0.9

tee与xarge

管道中使用tee

[root@localhost ~]# ip ad | grep "inet " | tee ip.txt|awk -F "/" '{print $1}'|awk '{print $2}'
127.0.0.1
10.0.0.9

[root@localhost ~]# cat ip.txt 
    inet 127.0.0.1/8 scope host lo
    inet 10.0.0.9/24 brd 10.0.0.255 scope global dynamic ens33

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

#直接将内容写入date.txt文件中
[root@localhost ~]# date > date.txt

# 命令执行会输出至屏幕,但会同时保存一份至date.txt文件中
[root@localhost ~]# date |tee date.txt
2021年 12月 06日 星期一 19:18:40 CST
[root@localhost ~]# cat date.txt 
2021年 12月 06日 星期一 19:18:40 CST

管道中使用xargs

  • xargs参数传递,主动让一些不支持管道的命令可以使用管道技术
[root@localhost ~]# which cat | xargs ls -l
-rwxr-xr-x. 1 root root 54160 10月 31 2018 /usr/bin/cat

[root@localhost ~]# ls | xargs rm -fv

山林不向四季起誓 荣枯随缘