bash 子进程中的 stdout 和 stderr 重定向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30642021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
stdout and stderr redirection in child process
提问by Tomek
If I run a Bash script like this:
如果我运行这样的 Bash 脚本:
./script.sh 2>&1
stderr
will be redirected to stdout
.
stderr
将被重定向到stdout
.
If the script calls some tool inside (e.g. ls
) or spawns a new process, will these
child processes have their stderr
also redirected to stdout
?
如果脚本调用内部的某个工具(例如ls
)或产生一个新进程,这些子进程是否stderr
也会重定向到stdout
?
回答by cdarke
Creating a child process on UNIX/Linux uses a procedure generically known as a fork. What this does is to copy almost the entire process address space of the current process (program code, data, almost everything) to the child. The Process IDentifier (PID) is different in the child, but almost everything else is the same.
在 UNIX/Linux 上创建子进程使用通常称为fork 的过程。这样做是将当前进程的几乎整个进程地址空间(程序代码,数据,几乎所有内容)复制到子进程。进程标识符 (PID) 在子进程中是不同的,但几乎所有其他内容都相同。
One of the items in a process which is copied is the file descriptor table. This is like an array. There is an entry for each file which is open, and by convention the first three, 0, 1, 2, are the standard streams, stdin, stdout, stderr. That explains the numbers used in 2>&1
. When we do redirection, it is these three entries that are changed in the child. That is done by the shell, since at this stage our child process is another shell process.
复制的进程中的项目之一是文件描述符表。这就像一个数组。每个打开的文件都有一个条目,按照惯例,前三个 0、1、2 是标准流、stdin、stdout、stderr。这解释了2>&1
. 当我们进行重定向时,在 child中更改的正是这三个条目。这是由 shell 完成的,因为在这个阶段我们的子进程是另一个 shell 进程。
Now comes the magic part, generically known as exec. If we want to run a different program, like ls
, we can switch programs within the process. So now the new program starts from the beginning, but certain core items are retained. Things like the user, group, current directory, umask, and the file descriptor table are all retained for use by the new program.
现在是神奇的部分,通常称为exec。如果我们想运行一个不同的程序,比如ls
,我们可以在进程内切换程序。所以现在新程序从头开始,但保留了某些核心项目。用户、组、当前目录、umask 和文件描述符表等内容都保留供新程序使用。
So, if the file descriptor table was altered previously, the new program inheritsthose changes. There is nothing to stop the program from overriding those settings and using different files, but that is rarely done.
因此,如果文件描述符表之前被更改,新程序将继承这些更改。没有什么可以阻止程序覆盖这些设置并使用不同的文件,但很少这样做。
All this behaviour is by default. Programs can change which file descriptors and other items are retained across the fork/exec boundary, but they usually don't.
所有这些行为都是默认的。程序可以更改跨 fork/exec 边界保留的文件描述符和其他项目,但通常不会。
回答by mana
Yep is the short answer. You can try it out yourself:
是的,简短的回答。你可以自己试试:
$ (>&1 echo "STDOUT is gone"; >&2 echo "I'm still here") > /dev/null
I'm still here
STDOUT
of the parent process [I'm starting a new shell with the braces:()
] will be sent to /dev/null
, and so will all the children's STDOUT
.
STDOUT
父进程的 [我正在启动一个带大括号的新 shell:()
] 将被发送到/dev/null
,所有子进程的STDOUT
.