Bash 单命令行解释(3)--重定向

这是翻译系列文章的第3篇,参考原文链接
翻译的系列文章列表:

  1. Bash 单命令行解释,第一部分:文件操作
  2. Bash 单命令行解释,第二部分:字符串操作
  3. Bash 单命令行解释,第三部分:重定向(本篇)

Bash 单命令行解释,第三部分:重定向

这是 Bash One-Liners Explained 系列文章的第3篇。本文中将讲授 输入/输出重定向 。我将利用 bash 最佳实践,多变的 bash 方言和 bash 命令技巧,展示仅利用 bash 内建命令和外部程序命令构建命令流完成各种各样的任务需求。

参见系列文章的第一篇 Bash 单命令行解释,第一部分:文件操作 了解我的初衷。若这个系列文章完成后,我将放出其同名的电子书。正如我创作的其它系列文章-- awksedperl 一样,我的电子书 有 pdf 格式及方便在手机上看的格式(mobi 和 epub)。同时,像 perl1line.txt 一样,也有纯文本 txt 格式的文档。

也可参考我其它的高效使用 bash 的系列文章:

开始学习

第三部分:重定向

当你理解了 文件描述符(file descriptors) 的操作,将会觉得使用 bash 的重定向非常简单。当 bash 启动时,它将默认打开 3 个标准文件描述符 :stdin(0号文件描述符)stdout(1号文件描述符)stderr(2号文件描述符) 。你可以打开更多的文件描述符(诸如:345 ...),也可以关闭它们,你可以拷贝文件描述符 ,也可以从它那里读或写入到它。

文件描述符 总是指向某些文件(除非文件被关闭)。通常,bash 启动时会把3个标准文件描述符:stdin,stdout,stderr 通通指向终端。输入(stdin)来自终端的键入内容,所有的输出(stdout,stderr)显示在终端里。

假定你的终端是 /dev/tty0 ,下面是终端标准文件描述符之间的关系示意图:

当 Bash 执行一条命令时,它会 分支(fork) 一个子进程,这个子进程继承 fork 它的父进程的一切标准文件描述符(关于 fork ,详情参考手册命令 man 2 fork )。首先按照命令行指示进行 重定向输入/输出 后才 执行(exec) 命令(关于 exec ,详情参考手册命令 man 3 exec)。

对于想 bash 重定向 操作进阶的你,永远心中有个蓝图 -- 当重定向发生时,标准文件描述符如何变化 --,这个蓝图将极大地帮助到你。

1. 重定向标准输出到一个文件

$ command >file

符号 > 是输出重定向操作符。bash 先尝试打开重定向指向的文件(这里是文件 file)并可写入,如果成功,Bash 将 command 命令子进程的标准输出文件描述符指向打开的文件。如果失败,整个命令失败退出,结束子进程。

命令行 command >file 等同于命令行 command 1>file 。数字 1 代表 stdout,它是标准输出文件描述符 stdout 的文件描述符号。

下面是标准文件描述符改变的蓝图示意。Bash 打开文件 file 并确定可写入后,替换子进程的标准输出文件描述符1file 文件的文件描述符,自此,命令的所有输出将写入文件 file 中。

通常,你可使用形如 "command n>file" 的命令,表示此命令的 n 号标准输入/输出文件描述符指向 file

举例:

$ ls > file_list

重定向 ls 命令的输出到 file_list 文件(命令的输出写入到文件)。

2. 重定向命令的标准错误输出到文件

$ command 2> file

这里,将命令的标准错误输出(stderr 号 2)文件描述符重定向到文件。这里的数字 2 代表标准错误输出文件描述符。

下面是标准文件描述符表改变蓝图:

Bash 打开文件 file 并确定可写入后,替换子进程的标准错误输出文件描述符2file 文件的文件描述符,自此,命令的所有错误输出由原来写入 stderr 中改写入文件 file 中。

3. 重定向标准输出和标准错误输出到文件

$ command &>file

上面这行命令中 "&>" 表示把所有的标准输出文件描述符(stdoutstderr )重定向到 file 文件描述符。&> 是 Bash 快速引用所有标准输出描述符(12)的简写。

下图是标准文件描述符改变示意图:

这里你看到所有的标准输出( stdout 和 stderr )都指向 file 文件的文件描述符。

有不同的几个方法将所有标准输出重定向到一个目标。可以按顺序一个接一个地重定向:

$ command >file 2>&1

上面命令是较通用的重定向所有标准输出到文件的方法。首先,标准输出(stdout)重定向到 file 文件(这步是先运行 ">file" 的结果)。之后,标准错误输出(stderr)重定向到 已重定向过的 stdout(&1) 上 (通过 "2>&1") 。因此,所有的标准输出都重定向到 file 上。

Bash 在命令行解析时,发现有多个重定向操作时,按从左到右的顺序依次解释处理。让我们按 Bash 执行顺序,单步分析,更好地理解它。一开始,Bash 在执行命令前,其3个标准输入/输出文件描述符都指向终端。示意图如下:

首先,Bash 处理第一个重定向 ">file" 。之前,我们见过这个示意图。它的标准输出(stdout)指向终端:

下一步解释处理重定向操作 "2>&1",这个操作的含义是使标准错误输出文件描述符(stderr 号 2)成为 1号标准输出文件描述符(stdout)的副本(重定向 2 到 1 的当前引用)。我们得到如下示意图:

所有的标准输出描述符都重定向到 file 文件。

然而,小心不要把 command >file 2>&1 写成 command 2>&1 >file ,它们是不同的!

Bash 对重定向指令的顺序敏感!后一命令仅仅把标准输出1(stdout) 重定向到 file 文件,而 标准输出2(stderr) 仍然输出到终端。理解为什么,让我们再进行单步分析,看看发生了什么。初始示意图如下:

Bash 从左到右一步步处理重定向,首先遇到 "2>&1" ,因此将 2 (stderr) 重定向与 1(stdout) 相同,即都指向终端,示意图如下:

现在,Bash 看到第2个重定向操作符 ">file" ,它重定向 1(stdout) 到 file 文件,示意图如下:

看到了什么,1(stdout) 重定向到了 file 文件,但 2(stderr) 仍指向终端,所有写到 stderr 的都显示到屏幕。所以,在使用重定向时,要非常非常小心给出它的操作循序!

另外在 Bash 中要注意:

$ command &>file

操作含义,与下面命令形式完全相同:

$ command >&file

但推荐第一种形式写法。

4. 舍弃命令的屏幕输出

$ command > /dev/null

特殊文件 /dev/null 抛弃所有写入它的内容(译注:可认为 /dev/null 是一个大小恒为0的文件,向它写入任何内容,它都会将它清空,保持文件大小为 0 。把它拷贝覆盖已有文件的动作也是把文件内容清空的方法)。下面是标准文件描述符示意图:

类比地,组合之前学过的命令,我们可以舍弃命令的输出和错误输出,命令如下:

$ command >/dev/null 2>&1

或简写成:

$ command &>/dev/null

相应的标准输入输出描述符示意图如下:

5. 重定向文件内容作为命令的输入

$ command <file

这里, Bash 在执行命令前,试图打开 file 文件并可读。若打开文件失败,命令失败退出。若打开读取文件成功,将使用打开的文件描述符作为命令的标准输入描述符(stdin 号 0)。

上述动作完成后的标准输入输出描述符表示意图如下:

下面是个例子,假定你想从 file 中读取其第1行赋值给变量,命令如下:

$ read -r line < file

Bash 的内建命令 read 从标准输入读取单行数据。 使用输入重定向操作符 < 使它从 file 文件中读取第1行数据。

6. 重定向多行文本到命令的输入

$ command <<EOL
>你
>多行
>文本
>输入
>到这儿
>EOL不是唯一文字
>  EOL
>EOL

这里,我们使用 即入文档(here-document) 重定向操作符 "<<MARKER" 的功能。这个操作指示 bash 从标准输入(stdin 0)读取多行输入,直到某行(最后一行)只包含 MARKER 且无前导空白即退出输入。最后一行的终止输入标志不会附加到输入中。将最终的多行输入给命令。

下面是个一般的例子。假设你拷贝了一堆的网上的网址(URLs)在系统剪贴板里,你想去掉所有的前缀 http:// ,快速的单行命令如下:

$ sed 's|http://||' <<EOL
http://url1.com
http://url2.com
http://url3.com
EOL

这里使用即入文档重定向符,将多行网址记录输入给 sed 命令,"sed" 命令使用正则表达式将所有行记录中的 http:// 删除。

以上例子输出:

url1.com
url2.com
url3.com

7. 重定向单行字符串文本到命令输入

$ command <<< "foo bar baz"

举个例子,假如你想系统剪贴板里的文本当作某个命令的输入(文本是命令的参数或选项),可能的办法是:

$ echo "粘帖剪贴板内容" | command

现在你可以使用下面命令:

$ command <<< "粘帖剪贴板内容"

当我学会这个技巧,它改变了我的人生!

8. 重定向所有的错误输出到一个文件

$ exec 2>file
$ command1
$ command2
$ ...

上述第一个命令行使用了 Bash 内建命令 exec 的功能,如果使用它重定向了标准输入输出(演示中是 2 号标准输出 stderr ),它在本 shell 中永久有效!除非你再次修改它或退出这个 shell 。

例子中,使用 exec 2>file 命令将 2 号标准输出(stderr)重定向到 file 文件。之后,在这个 shell 环境里所有命令的标准错误输出都重定向到 file 文件中。这是非常有用的一个技巧。当你想把所有命令或脚本中的运行记录到一个日志文件里,而又不想在每条命令中都繁琐地输入重定向操作。

概括地讲,exec 命令的主要功能是不创建子进程地调用一个 bash 命令或脚本并执行,若命令行中指定了命令或脚本,当前 shell 将被替换。我们演示的命令,在 exec 后并未给出任何命令,这仅仅利用了 exec 的执行重定向的功能,并无 shell 被替换。(译注:个人觉得 exec 是个较分裂的命令。推荐参考这个 链接 中对 exec 命令的解释。或直接看这个 AskUbuntu 中的回答)

9. 创建用户的文件描述符做为自定义的输入描述符

$ exec 3<file

这里,我们再次使用 exec 命令进行重定向的设置,指定 3<file 的意思是打开 file 文件可读取,并将其分配给当前 shell 的 3 号输入文件描述符。当前 shell 的输入输出文件描述符示意图如下:

现在就可以从3号输入文件描述符读取,如下命令:

$ read -u 3 line

上面的命令从 3 号输入文件描述符(重定向到 file 文件)中读取。

或用常规命令,诸如 grep 操作3号输入文件描述符:

$ grep "foo" <&3

这里,3号输入文件描述符通过重定向代替了 grep 命令的默认 stdin 输入。一定要记住,资源有限,故使用完用户自打开的文件描述符后,要及时关闭它,释放描述符号。可以再次使用。

使用完3号文件描述符后,可以关闭它,使用如下命令:

$ exec 3>&-

这里似乎3号文件描述符被重定向给 &- 实际上,&- 就是 关闭这个文件描述符 的一种语法。

10. 创建用户的文件描述符做为自定义的输出描述符

$ exec 4>file

这里,简单地指示 bash 打开可写 file 文件,并将其文件描述符重定向成为4号输出描述符。当前 shell 的输入输出文件描述符示意图如下:

正如你在上图所见,输入输出文件描述符并未按顺序来,用户可自由指定 0 只 255 之间的数字做为自定义打开的文件描述符号。

现在,简单往4号输出文件描述符中写入:

$ echo "foo" >&4

同样,可以关闭4号输出文件描述符:

$ exec 4>&-

学会使用自定义输入输出文件描述符,一切都是那么简单!

11. 打开文件用于读写

$ exec 3<>file

这里使用 bash 的菱形操作符 <> ,菱形操作符打开 file 文件用于读写。

所以,可以执行如下例子:

$ echo "foo bar" > file   # 将字符串  "foo bar" 写入 file 文件。
$ exec 5<> file           # 以读写方式打开 file 文件并重定向到5号描述符
$ read -n 3 var <&5       # 从5号输入输出描述符中读取前3个字符。
$ echo $var

上面最后命令将输出 "foo" ,只读出前3个字符。

也可写一些内容到 file 文件:

$ echo -n + >&5           # 在文件中第4字符位置写入 "+"
$ exec 5>&-               # 关闭5号文件描述符
$ cat file

上面会输出 foo+bar 。(译注:实践发现以永久重定向文件描述符读写文件,会保持读写位置)

12. 多个命令输出重定向到文件

$ (command1; command2) >file

上面例示使用 (commands) 运行命令操作,其中 bash 会将 () 中的命令在一个创建的子进程中运行。

所以这里的 command1command2 运行在当前 shell 的子进程,同时,bash 将他们的输出重定向到 file 文件。

13. 通过文件 shell 之间传递命令执行

打开2个 shell 模拟终端,在第1个 shell 中,输入命令:

$ mkfifo fifo
$ exec < fifo

在第2个 shell 中,输入命令:

$ exec 3> fifo; echo 'echo test' >&3

现在看第1个 shell ,发现 echo test 命令执行输出在第1个 shell 里。你可以在第2个 shell 中发送命令字符串给3号描述符的方式给第1个 shell 发送命令。

下面讲解它是如何做到的。

在 shell 1 中,使用 mkfifo 创建 命名管道 -- fifo 。一个命名管道(也称为 FIFO)性质与一般的管道相同,除了它是通过系统文件系统访问之外(创建命名管道将会在当前目录下创建一个以命名管道名命名的文件,这个文件第一个属性为 p 表示它为一个 管道(pipe),并且文件大小始终显示为 0)。它可供多进程读写(可供进程间通讯)。当进程间通过 FIFO --命名管道--交换数据时,系统内核并不会把数据写入文件存储系统。因此,命名管道文件大小永远为 0 。仅仅把文件系统中的文件名做为进程引用它的一个名称罢了。

下一命令 exec < fifo 重定向 shell 1 的输入为 fifo

接着,shell 2 重定向这个命名管道做为用户输出文件描述符,并分配号为 3 。然后给 3 号输出发送字符串 echo test ,这将传给 fifo 文件。

因此,shell 1 连接到 fifo 的标准输入进入 shell 1 命令行并执行!很容易吧!

(译注:原理很简单,自己开两个shell 去实践练习一下。别的不多说,只提醒一点:当 shell 1 把自己的标准输入重定向成命名管道之后,它就不能接受它自己终端的输入了。如何恢复它回到原始的输入?2个办法,1.是重定向前备份。2.是使用它原始的名称恢复,提示:输入仅可用 /dev/tty 。至于怎样让它执行命令?自己想想,你棒棒哒!)

14. 通过 bash 访问网站

$ exec 3<>/dev/tcp/www.bing.com/80
$ echo -e "GET / HTTP/1.1\n\n" >&3
$ cat <&3

Bash 处理 /dev/tcp/host/port 作为特殊文件。它不需要在你的文件系统中存在。这个只为 Bash 通过它打开指定主机的网络接口。

以上例子,首先打开可读写3号输入输出文件描述符指向 /dev/tcp/www.bing.com/80 ,它将链接到 www.bing.com 网站的端口 80 。

下一步,向3号文件描述符写入 'GET / HTTP/1.1\n\n' (发送HTTP请求),然后使用 cat 命令简单读取3号文件描述符的内容。

类似地,你可以通过 /dev/udp/host/port 创建特殊文件用于 UDP 连接。

使用 /dev/tcp/host/port 的方法,你甚至可以在 Bash 中写出端口扫描的命令或脚本!

(译注:原文示例使用的是谷歌,我这里换成了必应。实验了一下,可能由于现在网站都使用 SSL 的缘故,第一次会获得一个包含错误提示的 HTTP 响应内容,连接就关闭了)

15. 当重定向输出时阻止写入已有文件

$ set -o noclobber

上面的命令打开当前 shell 的 noclobber 选项。这个选项阻止当前 shell 使用重定向 '>' 操作覆盖写入已有的文件。

如果你输出重定向的文件是一个已有文件,将会得到一个错误提示:

$ > exFile
$ echo test > exFile
bash: exFile: cannot overwrite existing file
#bash: exFile: 不能覆写已有文件

如果你完全确定就是要覆盖写入已有文件,可以使用 >| 重定向符:

$ echo test >| exFile
$ cat exFile
test

这个操作符成功超越 noclobber 选项。

16. 将输入重定向到一个文件和输出到标准输出

$ command | tee file

这个 tee 命令超级方便,虽然它不是 bash 的内建命令但很常用。它能把收到的输入流输出到标准输出和一个文件中。

如上例子,它将 command 命令的输出分别输出到 shell 屏幕和一个文件。

下面是它工作原理示意图:

17. 将一个处理进程(命令)的输出重定向到另一个处理进程(命令)的输入

$ command1 | command2

这是简单的管道。我确定每个人都熟悉它。我放它到这里只是为了教程的完整。仅仅提醒你,管道 的本质就是将命令 command1输出 重定向到 command2 命令的 输入

可以用图示意如下:

上图可见,所有到达 command1 标准输出(1 stdout)的内容都被重定向到了 command2 的标准输入(0 stdin)。

更进一步请参考手册命令 man 2 pipe .

18. 发送一个命令的标准输出和标准错误输出到另一命令进程

$ command1 |& command2

这个操作符在 bash 4.0 版本后出现。 |& 重定向操作符通过管道将 command1 命令的标准输出和标准错误输出都发到 command2 命令的标准输入。

最新的 bash 4.0 版 的新功能未广泛普及前,旧的,方便的方法是:

$ command1 2>&1 | command2

下面是标准输入/输出描述符 的变化示意图:

前面的操作先将 command1 的 stderr(2) 重定向到 stdout(1) ,然后通过管道将标准输出重定向到 command2 的标准输入 stdin(0) 。

19. 为创建的文件描述符赋名

$ exec {filew}>output_file
#译注:引用命名文件描述符,使用 &$ 如下命令:
$ echo test >&$filew    #译者加的命令

命名文件描述符 是 bash 4.1 版后的功能特性。以 {varname}>output_file 定义了名为 varname 的输出文件描述符到指定文件。你可以通过其名称、文件描述符号正常使用它。Bash 在内部会给它分配一个空闲的文件描述符号。(译注:这个命令很容易和临时重定向到一个文件混淆!关于如何用其名称引用它,我写到上面的代码注释里。如何找到其文件描述符号,参见译注1.

20. 重定向操作的顺序

你可以把重定向操作放到命令行的任何位置。看看下面3个例子,它们效果一样:

$ echo hello >/tmp/example

$ echo >/tmp/example hello

$ >/tmp/example echo hello

喜欢上了 bash !

21. 交换标准 stdout 和 stderr

$ command 3>&1 1>&2 2>&3

这里,首先将 stdout(&1) 复制一个副本 &3 --3号文件描述符-- ,再使 stdout(&1) 成为 stderr(&2) -- 2号文件描述符-- 的副本,最后使 stderr(&2) 成为 &3 的副本。这样将 stdout 和 stderr 进行了交换。

让我们用图示展示每步过程。下面是命令开始时的文件描述符状态图示:

然后,3>&1 重定向操作符指示,创建 3号输出文件描述符指向跟 &1 相同:

下一个1>&2 重定向操作符指示,将 1号标准输出文件描述符指向跟 &2 相同:

下一个2>&3 重定向操作符指示,将 2号标准输出文件描述符指向跟 &3 相同(即原始的 &1):

如果想关闭不再有用的好人 &3 --3号文件描述符-- ,见如下命令:

$ command 3>&1 1>&2 2>&3 3>&-

之后的文件描述符表示意如下:

如你所见,文件描述符 1号 和 2号 已经交换。

22. 重定向 stdout 到一个进程,stderr 到另一进程

$ command > >(stdout_cmd) 2> >(stderr_cmd)

这行命令使用了重定向命令替换展开操作符 >() 。它将会运行 () 中的命令。而其标准输入通过匿名管道连接到了 command 的标准输出。接着下一个 >() 操作符将其标准输入连接到了 command 的标准错误输出。

对于上面的例子,第一个命令替换 >(stdout_cmd) 可能使 bash 返回 /dev/fd/60 文件描述符。同时,第二个命令替换 >(stderr_cmd) 可能使 bash 返回 /dev/fd/61 文件描述符。这2个文件描述符由 bash 实时创建为等待读取的命名管道。它们都等待某些命令进程往里写,以便它们读取。

所以,上述命令展开后可能是这样:

$ command > /dev/fd/60 2> /dev/fd/61

现在可看得清楚些, command 的 stdout 重定向到 /dev/fd/60 , stderr 重定向到 /dev/fd/61

command 输出,内部进程 'stdout_cmd' 的命令执行将接受。当 command 的错误输出,内部进程 'stderr_cmd' 的命令执行将接受。

23. 找出每个管道命令的退出码

让我们看一下几个命令用管道串起来的例子,如下命令:

$ cmd1 | cmd2 | cmd3 | cmd4

你想找出这里每个命令的退出状态码,该如何做?有没有一个简便的方法获取每个命令的退出状态码,而不是 bash 简单给出的最后一条命令的退出状态码。

Bash 的开发者想到了这点,他们加入了一个名为 'PIPESTATUS' 的数组变量来保留管道命令流中每个命令的运行退出状态码。

数组变量 PIPESTATUS 中的每个数字都对应于相应位置命令的退出状态码。下面是个例子:

$ echo 'men are cool' | grep 'moo' | sed 's/o/x/' | awk '{ print $1 }'
$ echo ${PIPESTATUS[@]}
0 1 0 0

上面例子中,命令 grep 'moo' 失败,因此数组变量 PIPESTATUS 中的第2个数为 1 。

建议

建议研究 bash 高手们的百科 演示重定向教程bash 版本进化.

欢迎指正

享受文中所说的方法和技巧使用的乐趣吧,并且让我知道您的想法。也许我漏掉了什么,非常乐意收到您的指正。

----------------------------------------

----------------------------------------

译注

1. 如何发现当前 bash 的所有文件描述符

以下内容,译者受网文 Linux: Find All File Descriptors Used By a Process 启发,针对在 bash 中发现其所有文件描述符的任务进行创作。

一、找到当前 bash 进程 ID -- PID

方法1:使用查看进程命令,如 ps 命令

语法:

ps aux | grep [程序名称]

ps 命令,参考本站wiki ps 命令(查看进程)
对于我们的情况,程序名称 是 bash ,命令如下:

$ ps aux | grep bash

可能的输出如下:

aman      7146  0.0  0.2  30748  5728 pts/4    Ss   09:42   0:00 bash
aman      7978  0.0  0.2  24432  5516 pts/18   Ss+  13:56   0:00 bash
aman      8022  0.0  0.0  15964   928 pts/4    S+   14:10   0:00 grep --color=auto bash

这里,我专门打开了2个 shell ,哪个是我们当前的 shell 呢?方法很多,使用 tty 命令找出当前的 tty 与上面的输出对比。找到本 shell 的 PID 是 7146

方法2:使用 pidof 命令

语法:

pidof [程序名称]

这个方法不适用同时开了多个 shell 的例子,但只有一个 shell 时会很简单,如下命令:

$ pidof bash
7146

二、根据 bash 的 PID 找到其使用的所有文件描述符

方法1:查看 /proc/pid/fd 目录

如下所示命令及输出:

$ ls -l /proc/7146/fd
total 0
lrwx------ 1 aman aman 64 12月 27 09:42 0 -> /dev/pts/4
l-wx------ 1 aman aman 64 12月 27 09:42 1 -> /dev/pts/4
l-wx------ 1 aman aman 64 12月 27 09:42 10 -> /home/aman/test/nFD
lrwx------ 1 aman aman 64 12月 27 09:42 2 -> /dev/pts/4
lrwx------ 1 aman aman 64 12月 27 12:02 255 -> /dev/pts/4

我之前在这个 shell 下,使用 $ exec {FD1}> nFD 命令创建了一个永久命名文件描述符重定向到了当前目录下的 nFD 文件。在这里我们看见 bash 内部给它分配了文件描述符号 10 。这样,你在重定向输出时就即可使用 &$FD1&10 都会输出到 nFD 文件。

我的运行示意如下:

$ echo 'line 1' >&10
$ echo 'line 2' >&$FD1   #这行命令与上行输出到相同目的地
$ cat nFD
line 1
line 2
方法2:使用 lsof 命令

语法:

lsof -a -p {输入PID}

lsof 命令,参考 ’ lsof command ' 。我的命令示意如下:

$ lsof -a -p 7146

输出:

COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    7146 aman  cwd    DIR    8,5     4096 178864 /home/aman/test
bash    7146 aman  rtd    DIR    8,5     4096      2 /
bash    7146 aman  txt    REG    8,5  1037528 134435 /bin/bash
bash    7146 aman  mem    REG    8,5   101200 265464 /lib/x86_64-linux-gnu/libresolv-2.23.so
...
...
...
bash    7146 aman    0u   CHR  136,4      0t0      7 /dev/pts/4
bash    7146 aman    1w   CHR  136,4      0t0      7 /dev/pts/4
bash    7146 aman    2u   CHR  136,4      0t0      7 /dev/pts/4
bash    7146 aman   10w   REG    8,5       16 178735 /home/aman/test/nFD
bash    7146 aman  255u   CHR  136,4      0t0      7 /dev/pts/4

见上面输出倒数第二行,可知 nFD 文件的重定向文件描述符号为 10

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!