[linux]重定向

782 阅读5分钟

1 说在前面

  • 基于Centos 6.9
  • 有经验的可以直接跳到最后总结
  • 重定向中的一个细节,暂未搞清楚
  • 如果大家有兴趣(评论下),我可以把高阶的再整理出来

2 重定向

2.1 文件描述符

首先来看三个文件

[root@testing ~]# ll /dev/std*
lrwxrwxrwx. 1 root root 15 Jun  7  2019 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 Jun  7  2019 /dev/stdout -> /proc/self/fd/1
lrwxrwxrwx. 1 root root 15 Jun  7  2019 /dev/stderr -> /proc/self/fd/2

这3个就是系统的文件描述符:

 1. stdin     标准输入    文件描述符fd=0
 2. stdout    标准输出    文件描述符fd=1 [注:可以认为是标准正确输出]
 3. stderr    标准错误    文件描述符fd=2

那什么是重定向呢?涉及到几个符号,初阶的就是:

 1. >   输出重定向 
 2. >> 输出追加重定向
 3. <   输入重定向
 4. &  文件描述符

怎么来操作重定向呢?看鸟哥的解释吧:

image.png

那我们来看一些实例 ##2.2 重定向标准输出

[root@testing ~]# cat /etc/redhat-release  
#正常看一个文件
CentOS release 6.9 (Final)
#输出到屏幕上(标准输出,且是正确的结果)
[root@testing ~]# ll /home/version
ls: cannot access /home/version: No such file or directory
#先确认一个文件不存在,后续之用
[root@testing ~]# cat /etc/redhat-release >/home/version
#执行命令后加>,再接一个文件,此时屏幕上就没有输出信息了,输出到哪里去了?
[root@testing ~]# cat /home/version 
CentOS release 6.9 (Final)    
#输出信息跑到这个文件里来了
[root@testing ~]# cat /etc/redhat-release 1>/home/version
#>和1>是一样的,1是默认值,命令后跟的空格1,这个数字就是文件描述符
[root@testing ~]# cat /home/version 
CentOS release 6.9 (Final)
#1>和>的效果一样
[root@testing ~]# uname -a >/home/version
#如果再执行一个其他命令,输出到刚才的同一个文件中呢
[root@testing ~]# cat /home/version 
Linux testing 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21     19:29:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
#发现上一次的内容被覆盖了,只保留了最新的内容

这里能发现几个特征,在重定向>的时候

  1. 重定向>,等价于1>,1是默认值,标准输出

  2. 重定向的时候文件可以不存在,不存在就新建,存在就先清空再输出到文件 基于此,一个小技巧,清空文件最快的方法

     [root@testing ~]# cat /home/version 
     CentOS release 6.9 (Final)
     [root@testing ~]# >/home/version
     #重定向到一个文件,但什么都不做,那就是清空文件
     [root@testing ~]# cat /home/version 
     [root@testing ~]# 
     #文件被清空了
    

##2.3 重定向标准错误 系统中的错误就很多了,包括但远远不限于

  1. 文件、目录不存在
  2. 命令不存在
  3. 权限不足
  4. 依赖缺失 ...

这样我们可以来重定向标准错误,跟标准输入一样一样的

[root@testing ~]# su - china
[china@testing ~]$ lk
-bash: lk: command not found
#china用户没有lk这个命令,这是错误信息!
[china@testing ~]$ lk 2>./error.info
#刚才的错误重定向到error.info这个文件中
[china@testing ~]$ cat error.info 
-bash: lk: command not found
#验证了我们的想法,下面是另外一个例子,不赘述
[china@testing ~]$ ls -l /root/
ls: cannot open directory /root/: Permission denied
[china@testing ~]$ ls -l /root/ 2>./error.info2
[china@testing ~]$ cat error.info2
ls: cannot open directory /root/: Permission denied
[china@testing ~]$ 

##2.4 重定向追加 追加的意思就是append,尾部插入,保留原文件的内容,在尾部追加,如果文件不存在,也是创建新文件(但没有清空这一步)

[root@testing ~]# uname -a>/home/system.info
[root@testing ~]# cat /home/system.info 
Linux testing 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21     19:29:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@testing ~]# uptime >>/home/system.info
#标准正确输出重定向追加
[root@testing ~]# uptime >>/home/system.info1
#系统不存在该文件
[root@testing ~]# cat /home/system.info
Linux testing 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21     19:29:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
 08:34:50 up  1:16,  4 users,  load average: 0.00, 0.00, 0.00
[root@testing ~]# cat /home/system.info1
 08:34:52 up  1:16,  4 users,  load average: 0.00, 0.00, 0.00

标准错误同理,不再赘述

##2.5 标准错误和标准正确都重定向到某个文件中 系统中有些命令同时会有错误和正确的输出,特别是脚本是多条命令的组合,那非常有可能有正确和错误2部分。

  • 以普通用户执行find / -name profile,
  • 一个脚本有正确和错误的命令:

常规的思路是 command >file 2>>file,或者command 2>file 1>>file 但这其实是有问题的也是让我费解的地方。

[root@testing ~]# cat test.sh 
#写一个简单的脚本,包含一条正确的命令和一条错误的命令
uname
lk
[root@testing ~]# ./test.sh 
Linux
./test.sh: line 2: lk: command not found
[root@testing ~]# ./test.sh >file1 2>file2
#正确输出到file1,错误输出到file2
[root@testing ~]# cat file1
Linux
[root@testing ~]# cat file2
./test.sh: line 2: lk: command not found
#没毛病
[root@testing ~]# ./test.sh >file1 2>>file1
[root@testing ~]# cat file1
Linux
./test.sh: line 2: lk: command not found
#没毛病+1

下面来毛病了,就是我不懂的地方了!

[root@testing ~]# cat test.sh
uname
lk
uname
#脚本里面的命令是正确-错误-正确
[root@testing ~]# ./test.sh >file1 2>>file1
#正确输出到file1,错误追加到file1
[root@testing ~]# cat file1
Linux
Linux
.sh: line 2: lk: command not found
#注意:文件内容是正确在一块,错误在一块
[root@testing ~]# ./test.sh 2>file1 >>file1
#**可如果这么写呢?**
[root@testing ~]# cat file1
./test.sh: line 2: lk: command not found
Linux
#丢了一个正确的!我也不知道为何。

标准输出和标准错误都要定向到一个文件,正确的姿势应该是这样的,不建议用分别输出、结合追加的方式 [root@testing ~]# ./test.sh >file 2>&1 [root@testing ~]# cat file Linux ./test.sh: line 2: lk: command not found Linux

画了个草图

image.png

给出示例:

[root@testing ~]# ./test.sh >file 2>&1
#方法1
[root@testing ~]# cat file
Linux
./test.sh: line 2: lk: command not found
Linux
[root@testing ~]# ./test.sh 2>file1 1>&2
#方法2
[root@testing ~]# cat file1
Linux
./test.sh: line 2: lk: command not found
Linux
[root@testing ~]# ./test.sh &>file2
#方法3
[root@testing ~]# cat file2
Linux
./test.sh: line 2: lk: command not found
Linux

3 总结

  • 标准输出重定向 command >file
  • 标准输出追加重定向 command >>file
  • 标准错误重定向 command 2>file
  • 标准错误追加重定向 command 2>>file
  • 标准输出和标准错误重定向到1个文件
    • command >file 2>&1
    • command 2>file 1>&2
    • command &>file

这只是初阶的,囧