Shell 我可以创建自己的不同于stdout和stderr的输出流吗?

Shell 我可以创建自己的不同于stdout和stderr的输出流吗?,shell,stdout,stderr,Shell,Stdout,Stderr,unistd.h的UNIX手册页说明: The following symbolic constants are defined for file streams: STDIN_FILENO File number of stdin. It is 0. STDOUT_FILENO File number of stdout. It is 1. STDERR_FILENO File number of stderr. It is 2. 将我所有的头文件都变灰,我发现这是真的 [/usr]gr

unistd.h
的UNIX手册页说明:

The following symbolic constants are defined for file streams:
STDIN_FILENO  File number of stdin.  It is 0.
STDOUT_FILENO File number of stdout. It is 1.
STDERR_FILENO File number of stderr. It is 2.
将我所有的头文件都变灰,我发现这是真的

[/usr]grep -r "STDIN_FILENO" include
include/unistd.h:#define    STDIN_FILENO    0   /* Standard input.  */

[/usr] grep -r "STDOUT_FILENO" include 
include/unistd.h:#define    STDOUT_FILENO   1   /* Standard output.  */

[/usr]grep -r "STDERR_FILENO" include
include/boost/asio/detail/impl/handler_tracking.ipp:  ::write(STDERR_FILENO, line, length);
include/unistd.h:#define    STDERR_FILENO   2   /* Standard error output.  */
即使它们已定义,但它们似乎从未被我机器上的任何其他std头文件使用。我觉得很奇怪。可能在其他地方使用了0、1和2,而不是定义的宏。宏的存在只是为了作为流配置方式的指示而被引用

无论如何,我们可以通过以下操作在shell中捕获特定的输出流:

./program 1> stdout.txt
./program 2> stderr.txt
./program > both.txt 2>&1
我想创建自己的输出流,并通过以下操作捕获它:

./program 3> mine.txt
我试着搜索
unistd.h
中包含的其他文件,看看
std::cout
std::cerr
是如何工作的,但正如你可能想象的那样,我迷路了


我更感兴趣的是你是否能做到这一点,而不是这是否是一个好主意。

当你调用
open
时,它会返回一个数字。您将该数字传递给
读取
写入
。但是,您可以运行如下命令:

mycommand 3 3>bloop.txt

在mycommand中,将argv[1]转换为一个数字,并将其传递给write。

打开的文件描述符由子进程继承。操作系统负责将一个进程与三个标准流连接起来,但您可以自由地执行任意数量的s,然后执行一个(最好在前一个之后)。然后,孩子可以扫描打开的文件描述符列表(在
/proc/self/fd/
中),或者以某种方式“知道”要使用哪些描述符

下面是一个用C编写的小示例

#include/*errno*/
#包括/*atoi、fprintf*/
#包括/*退出成功,退出失败*/
#包括/*strerror,斯特伦*/
#包括/*写入*/
static const char*const message=“你好,世界\n”;
int main(int argc,字符**argv)
{
int-fd;
int i;
对于(i=1;i
程序的调用方负责打开程序应该写入的任何文件描述符,并通过其命令行参数告诉它

要将连接到文件
redir
的打开文件描述符3传递给它,我们可以使用shell的实用程序打开文件描述符并执行子脚本

$exec 3>重拨。/a.out 3
这将在子shell退出后关闭当前shell,因此您可能希望在子shell中尝试它:

$sh-c'exec 3>redir./a.out 3'
或者,不要使用
exec
,而是使用前面提到的重定向语法@。这里,我们正在写入标准错误输出(2),以及文件描述符3和4,其中我们将3重定向到标准输出(1),将4重定向到文件
redir

$。/a.out 2 3 4 3>&1 4>重拨
你好,世界
你好,世界
$cat redir
你好,世界
这种文件描述符的继承在服务器进程中被大量使用,这些进程让他们的(非特权)子进程拥有文件描述符来记录文件、监狱外的文件、TCP连接等等


不幸的是,在调用子进程之前忘记关闭文件描述符是一个常见的错误,可能与安全相关。有一个模块可以检查这一点。

请查看Bash文档。文件描述符由bash从登录或终端程序继承,然后由您的程序继承。如果您使用GCC,您可能会发现它们的非标准库:
,它允许您从POSIX文件描述符创建一个
std::filebuf
(从而创建一个
std::fstream
),此函数的第一个参数。文件描述符(fd)