Linux IO,标准流和重定向

在Linux中,有三个标准输入流,标准输入(0-stdin),标准输出(1-stdout)和标准错误(2-stderr)。在本文中,我们将在bash命令行中讨论实际用途重定向,标准流及其文件描述符,并提供有关如何使用每个重定向(包括重定向)的示例。

标准流

通常,在Linux和计算机编程中,标准流是程序与其环境之间的输入和输出(I / O)通信通道。这三个标准流是标准输入(stdin),标准输出(stdout)和标准错误(stderr)。流通常连接到执行它们的终端,但是可以使用重定向运算符和/或管道进行更改。

以下是有助于可视化数据流及其文件描述符的图形。

文件描述符

Linux通常将三个标准流表示为文件描述符,这是一张有助于理解关系的表。

文件描述符不限于三个标准流,而是最常用的预定义流。可以创建自定义文件描述符,但是我们将不在本文中介绍。

重定向运算符

重定向运算符是控制运算符的子集。它们允许您定向命令的输入或输出(流)。

输入运算符

输入运算符为命令或过程提供输入。左尖括号(<)表示此运算符。

输入运算符(rw)

输入运算符(rw)与输入运算符的作用相同,只是它以读/写模式打开文件。左右尖括号(<>)表示此运算符。如果该文件不存在,将创建它。由于大多数输入来自键盘或文件读取,因此很少使用。

输出运算符

输出运算符控制命令输出流。右尖括号(>)表示此运算符。如果您要重定向的文件不存在,将创建该文件。如果确实存在,它将被覆盖。

输出追加运算符

输出追加运算符与输出运算符的功能相同,只是将数据追加到文件。两个直角括号(>>)表示此运算符。如果您要重定向的文件不存在,将创建该文件。如果确实存在,此命令将向其附加数据而不是覆盖。

非标准运营商

非标准运算符同时控制标准输出(stdout)和标准错误(stderr)。这些运算符由与号,右括号或右双括号表示。一种覆盖(&>),一种附加(&>>)到输出文件。

管道操作员

管道运算符用于将命令的输出传递到另一个命令的输入。竖线(|)代表此运算符。恰当地命名的管道可以被认为类似于将液体从一个容器移动到另一个容器的物理管道。命令的输出在一侧进入管道,而在另一侧将管道作为另一命令的输入。

以下各节提供了使用管道操作器的示例。

标准输入-STDIN

标准输入是进入程序的数据流。这通常是从键盘输入的文本,但也可以将数据通过管道传输或重定向到程序。

键盘标准输入

cat命令是使用标准输入的程序的简单示例。默认情况下,cat接受标准输入并将其打印到显示器(标准输出)。

为了测试这一点,我们可以使用cat命令。打开终端并输入cat,然后从您喜欢的歌曲中输入一行,然后按Enter。
注意:完成后,按CTRL + D退出,cat程序将永远执行此操作。

$ cat
 Your lips move but I can't hear what you're saying

来自输入文件的标准输入

标准输入也可以来自输入文件。如果为cat提供一个文件作为参数,它将替换或重定向键盘上的标准输入到该文件中的数据。

要对此进行测试,请在终端中输入以下命令,然后按Enter。

$ cat ~/.bashrc

上面的命令将参数(〜/ .bashrc)作为标准输入,并在屏幕上输出文件的内容。

重定向的标准输入

标准输入也可以使用输入重定向运算符来自任何文件输出,该输入重定向运算符由小于号或左指向尖括号(<)表示。例如,您可以使用输入重定向来实现与上述相同的结果,如下所示:

$ cat ~/.bashrc

来自数据管道的标准输入

到目前为止,我们学习了如何通过参数或重定向从键盘或文件提供标准输入。但是,您也可以在输入流上从另一个程序的输出中提供标准输入。这称为管道,即使您不熟悉Linux,您也可能已经遇到了这个概念。垂直线(|)表示的管道基本上从一个命令获取输出,然后将其放入管道,然后从另一侧的管道出来并进入下一个命令。

要对此进行测试,请在终端中输入以下命令。

$ cat < ~/.bashrc
 .bashrc

head程序输出文件的前10行,并将其通过管道传输到cat作为标准输入(stdin),然后将其打印到标准输出(stdout)。

标准输出-STDOUT

标准输出是标准流,默认情况下将发送到显示监视器。终端通常是标准输出,但是您可以将输出通过管道传输或重定向到文件,另一个程序或设备。

显示标准输出

您可以将几乎所有命令的输出用作标准输出(stdout)的示例。在这里,我们将使用stat命令获取有关文件的状态信息,并将其显示在监视器上。

$ cat < ~/.bashrc
 .bashrc

如您所见,stat命令将文件名作为参数,进行了一些处理,然后将该文件的统计信息显示给监视器(stdout)。

标准输出重定向到文件

您可以将标准输出(stdout)重定向到文件。如果要保存输出以供以后使用或作为脚本的日志,这将很有用。

您可以使用输出重定向操作符将stdout重定向到文件,该操作符由大于号或右指向尖括号(>)表示。例如,您可以将stat命令的输出保存到名为output.txt的文件中,如下所示:

$ stat〜/ .bashrc> output.txt

这将创建一个名为output.txt的文件,并将stat命令的标准输出(stdout)放入其中。我们可以通过读取文件来验证这一点。

$ cat output.txt 
   File: /home/savona/.bashrc
   Size: 192           Blocks: 8          IO Block: 4096   regular file

使用此输出重定向将覆盖文件中可能已经存在的所有数据。如果要附加,请使用输出附加运算符,以两个尖括号(>>)表示。

$ stat ~/.bashrc >> output.txt

通过数据管道的标准输出

数据管道将输出从一个命令发送到另一个命令。在这里,我们将stat命令的输出通过管道传递到grep中,以仅提取文件的最后修改时间。

$ stat ~/.bashrc | grep -i modify
 Modify: 2019-02-03 09:03:25.750855221 -0500

stat命令输出进入管道并传递给grep进行处理。grep处理完数据后,会将输出发送到标准输出(stdout)。

标准错误-STDERR

标准错误(stderr)是来自进程的所有错误消息的目的地。默认情况下,这是显示屏,但是就像标准输出一样,它可以重定向。

显示标准误差

如果您经常使用命令行,那么错误输入肯定会导致屏幕上显示错误。这是标准错误(stderr)的示例。在这里,我们将向命令提供一个不存在的参数,它将使用stderr告诉我们。

$ ls zepplin
 ls: cannot access 'zepplin': No such file or directory

默认情况下,错误在屏幕上显示为stderr。

标准错误重定向到文件

就像其他流一样,您可以将stderr重定向到文件。常用于脚本编写,但对于使用命令行的任何人都很方便。要重定向stderr,可以使用与stdout(>)相同的输出重定向操作符。但是这一次,我们必须指定我们要使用文件描述符重定向stderr。如上表和图表所示,stderr的文件描述符为2。因此,我们将其重定向为:

$ ls zepplin 2> errors.txt

现在,文件errors.txt包含上述命令输出中的错误。

$ cat errors.txt 
 ls: cannot access 'zepplin': No such file or directory

正如我们在stdout部分中讨论的那样,使用单括号重定向将导致覆盖文件中当前存在的所有数据。要附加而不是覆盖,您必须使用附加重定向(>>)。

$ ls zepplin 2>> errors.txt

通过数据管道的标准错误

您不能直接将stderr传递给另一个命令。这是设计使然,以允许完整的错误报告。这是尝试(失败)将stderr传递到grep的示例。

$ ls zepplin floyd stones | grep zepplin
 ls: cannot access 'zepplin': No such file or directory
 ls: cannot access 'floyd': No such file or directory
 ls: cannot access 'stones': No such file or directory

ls命令将错误打印到屏幕上,而grep命令的作用就像没有收到任何输入一样。

但是,与大多数Linux一样,有多种方法可以完成同一任务。您可以使用它们的文件描述符将stderr重定向到stdout,然后将其通过grep传递。

$ ls zepplin floyd stones 2>&1 | grep zepplin
 ls: cannot access 'zepplin': No such file or directory

在下一节中,我们将讨论有关文件描述符的更多信息。

使用文件描述符进行重定向

非标准重定向需要文件描述符。在以上各节中,我们介绍了所有标准(输入/输出)重定向。下面,我们将概述一些使用文件描述符的其他重定向。

文件描述符用于重定向流。但是,您可以使用文件描述符做更多的事情,这比我们在这里介绍的要多得多。本节的目的是使您对文件描述符有一个基本的了解,并使您熟悉它们的基本用法。

将STDERR和STDOUT重定向到其他文件。

您可以将stderr和stdout都重定向到文件。这是一个例子:

$ ls zepplin floyd stones 1> output.txt 2> errors.txt

上面的命令将stdout(文件描述符1)发送到ouput.txt,将stderr(2)发送到errors.txt。我们可以通过读取这些文件来进行验证。

$ cat output.txt 
 floyd:
 dark-side-of-the-moon.txt
 the-wall.txt

$ cat errors.txt 
 ls: cannot access 'zepplin': No such file or directory
 ls: cannot access 'stones': No such file or directory

将STDERR和STDOUT重定向到同一文件。

如果愿意,可以将stderr和stdout都重定向到单个文件。为此,我们可以将stderr重定向到stdout,然后将stdout重定向到这样的文件:

$ ls zepplin floyd stones >alloutput.txt 2>&1

或者我们可以像这样使用简写(非标准)运算符:

$ ls zepplin floyd stones &> alloutput.txt

这两个命令都会产生相同的结果,所有stdout和stderr都发送到alloutput.txt文件。

$ cat alloutput.txt 
 ls: cannot access 'zepplin': No such file or directory
 ls: cannot access 'stones': No such file or directory
 floyd:
 dark-side-of-the-moon.txt
 the-wall.txt

在脚本中使用永久重定向

如果您正在编写脚本并希望重定向数据流而不添加重定向操作符或每一行,则可以使用像这样的exec命令。

#!/bin/bash
# Redirect all stdout to output.txt
exec 1> output.txt
# Redirect all stderr to errors.txt
exec 2> errors.txt

您可以在脚本中使用一个,两个或任意多个自定义文件描述符。

结论

了解标准流,文件描述符和重定向是精通命令行的重要组成部分。在本文中,我们介绍了很多内容,但仍然只是表面介绍。

每日科技资讯 | 20200810
每日科技资讯 | 20200809