这是我从我写的 stderr 读取的 C 程序
#include <uninstd.h>
#include <stdio.h>
int main(void) {
char buff[3];
read(2, buff, sizeof(buff));
printf("%s", buff");
return 0;
}
我的问题是如何向它发送 stderr。大多数搜索显示为 bash 重定向
command 2> file
但这会将 stderr 发送到文件。
我怎样才能传递到我的程序。就像点一样,
command 2 "somthing here" ./myprogram
感谢您的回答。
答案1
鉴于大多数参考书和文档总是将标准错误作为输出,这让许多人感到惊讶,事实上它通常是已经打开读+写。非常喜欢你的节目能从文件描述符 2 读取。
(注意:在这个答案中,我使用实际的文件描述符编号。C流例如stderr
不需要实际对应这些文件描述符,因为程序可以更改它们,并且它增加了谈论 C 流的作用的一层混乱。您的程序正在使用read()
。)
文件描述符2打开用于读写
对于在父进程中未使用重定向的登录会话中的程序,文件描述符 2(标准错误)通常是文件描述符 0(标准输入)的副本。它们都引用相同的底层文件描述,它通常是登录会话的终端(由ttymon
或在旧系统上getty
在会话开始时打开和复制)。
如果从文件描述符 2 读取,您将获得与从文件描述符 0 读取相同的输入。
顺便说一句:从文件描述符 2 中读取数据经常用于密码输入等操作;在该/dev/tty
设备推出之前,大约在 1977 年。从文件描述符 2 读取的原因是当文件描述符 0 已重定向到其他地方时(例如,在管道中间的情况),从原始终端获取输入。
尽管/dev/tty
POSIX 已经存在很长时间了,超过 40 年了,但它仍然要求文件描述符 2 也打开以供读取。
你的程序没有做什么
从文件描述符 2 读取另一个程序的输出是另一回事。你不能轻易做到这一点通过它自己,不将标准输出与标准错误合并。它通常涉及一系列3>&1 1>&2 2>&3
或类似的交换。一些 shell 通过调用允许在输出文件描述符 2 上使用管道
prog1 2| prog2
但这样的贝壳很少见,这并不是什么你的无论如何,程序都需要。
将输入发送到您的程序
如果您希望您的程序从文件描述符 2 读取内容,则可以读取某些内容其他与从终端相比,您当然可以重定向该文件描述符。你可以使用正常的输入重定向语法(<
shell 中的运算符),但程序中的库,甚至您在其他地方编写的其他代码,都会假设它们可以写入此文件描述符。
shell 允许您使用<>
重定向运算符来显式打开文件以进行读取和写入。这是您在重定向程序的文件描述符 2 时使用的。
./myprogram 2<>filename
除了 shell 重定向之外,还有很多工具可以操作文件描述符。例如:Laurent Bercot 的链式加载redirfd
工具,与 execline 一起提供,这个重定向看起来更像你的假设:
redirfd -u 2 filename ./myprogram
Bourne Again 和 Z shell(但不是 Almquist shell)等 shell 语法也为文件描述符 2 提供“此处文档”和“此处字符串”。请注意,文件描述符 2 已打开只读在这种情况下通过这些外壳。
./myprogram 2<<< "here string"
答案2
stderr
是为了写作,而不是阅读。有时它是一个dup
重复stdin
(例如,当所有 3 个输入/输出/错误都连接到终端时)。要读取另一个程序的 stderr,您可以将该程序的 stderr 重定向到另一个程序的 stdin。
例如 指向stdout
一个文件,然后stderr
指向./myprograms
's stdin
。
command 2>&1 >a_file | ./myprogram
答案3
bash
使用像and 之类的 shell zsh
(但不是普通的 POSIX sh
),您可以通过 将一个程序的标准错误重定向到另一个程序的标准输入firstprogram 2> >(second program)
。
例子:
$ perl -E 'say "perl stdout"; warn "perl stderr\n"' 2> >(awk '{print "awk", $0}')
perl stdout
awk perl stderr
答案4
要让 shell 设置输入重定向stderr
,您可以使用<
,<<
或<<<
并在文件描述符编号前加上前缀:
./myprog 2< somefile.txt
或者
./myprog 2<<< "some text"
但如果你stderr
像那样重定向,程序就不能输出到它,这意味着您不会看到程序(或其使用的任何库)可能尝试打印的任何错误消息,此外,程序还会因尝试写入这些消息而出现错误。
您可能需要重新考虑是否有其他方法可以完成您正在做的事情。至少,如果想法是为程序提供一些输入,请考虑使用例如 fd 3。