考虑这个示例 C 程序,它写入/dev/tty
但没有命令行选项来阻止它这样做。
#include <stdio.h>
int main (void) {
FILE* fout = fopen("/dev/tty", "w");
fprintf(fout, "Hello, World!\n");
fclose(fout);
}
我如何将其输出重定向到/dev/null
shell 脚本中?
PS我读过这个答案,但我不太明白。无论如何,我期待一个不会修改程序代码源的答案。
答案1
TL、博士:
script -c myprogram /dev/null </dev/null >/dev/null
/dev/tty
您不能像重定向标准输出那样“重定向” 。标准输出被定义为文件描述符。程序启动时会写入文件描述符 1 上已打开的任何文件。某些操作系统提供/dev/stdout
与标准输出等效的文件,但它是标准输出的“别名”。相反,/dev/tty
是一个文件名,它指的是进程的控制终端。如果程序打开/dev/tty
,则显式打开/dev/tty
,并且无法重定向。
您可以做的是使用与运行该程序的程序的控制终端不同的控制终端来运行该程序。执行此操作的一个简单方法是使用script
命令。最简单的形式:
script -c myprogram /dev/null >/dev/null
当myprogram
运行并打开时/dev/tty
,这是由 提供的终端script
,而不是运行的终端script
。script
当它检测到终端上的写入时,会执行什么操作,既写入其自己的标准输出,又写入指定的打字稿文件;因此我将script
的标准输出和打字稿文件都设置为/dev/null
.
如果myprogram
从终端读取,则从其自己的标准输入读取,因此您可能也script
希望将其重定向到。/dev/null
请注意,script
不会将 的退出状态传递myprogram
给其调用者。某些实现(例如 Debian 及其衍生版本中的实现)可以-e
选择执行此操作。
答案2
它是非常程序自行打开 /dev/tty 是不寻常的。如果您需要将某些内容打印到控制台,您只需写入标准输出,stdout
您可以将其重定向,如下所示吉尔斯展示。
你在这里唯一的选择是拦截库 fopen
调用,除非它被内联(这并不罕见)或底层操作系统open
调用并弯曲它。
这并不难。您需要编写一个包含所述open
函数的小库,该函数在“清理”其输入后依次调用实际open
函数(即,如果文件名是 /dev/tty,则将其替换为 /dev/null)。
运行程序并拦截和重定向系统调用展示了这是如何完成的。