【问题标题】:stdout and stderr redirection in child process子进程中的 stdout 和 stderr 重定向
【发布时间】:2015-08-18 22:58:35
【问题描述】:

如果我运行这样的 Bash 脚本:

./script.sh 2>&1

stderr 将被重定向到stdout

如果脚本调用内部的某些工具(例如ls)或产生一个新进程,这些 子进程的stderr 也重定向到stdout

【问题讨论】:

    标签: bash unix process stdout stderr


    【解决方案1】:

    是的,这是简短的回答。你可以自己试试:

    $ (>&1 echo "STDOUT is gone"; >&2 echo "I'm still here") > /dev/null
    I'm still here
    

    父进程的STDOUT [我正在用大括号启动一个新的shell:()] 将被发送到/dev/null,所有子进程的STDOUT 也将发送到。

    【讨论】:

      【解决方案2】:

      在 UNIX/Linux 上创建子进程使用通常称为 fork 的过程。这样做的目的是将当前进程的几乎整个进程地址空间(程序代码、数据、几乎所有内容)复制到子进程中。进程标识符 (PID) 在子进程中有所不同,但几乎所有其他内容都相同。

      进程中被复制的项目之一是文件描述符表。这就像一个数组。每个打开的文件都有一个条目,按照惯例,前三个 0、1、2 是标准流、stdin、stdout、stderr。这解释了2>&1 中使用的数字。当我们进行重定向时,这三个条目在子节点中发生了更改。这是由 shell 完成的,因为在这个阶段我们的子进程是另一个 shell 进程。

      现在是神奇的部分,通常称为 exec。如果我们想运行不同的程序,比如ls,我们可以在进程内切换程序。所以现在新程序从头开始,但保留了一些核心项目。诸如用户、组、当前目录、umask 和文件描述符表之类的东西都保留给新程序使用。

      因此,如果文件描述符表之前已更改,则新程序继承这些更改。没有什么可以阻止程序覆盖这些设置并使用不同的文件,但很少这样做。

      所有这些行为都是默认的。程序可以更改跨越 fork/exec 边界保留的文件描述符和其他项目,但它们通常不会。

      【讨论】:

        猜你喜欢
        • 2012-07-14
        • 1970-01-01
        • 1970-01-01
        • 2014-07-22
        • 1970-01-01
        • 2020-03-11
        • 2023-04-06
        • 2011-07-18
        • 1970-01-01
        相关资源
        最近更新 更多