如何判断stdout与stderr是否重定向至不同文件或终端
解决方案:判断stdout与stderr是否指向不同文件
核心思路
当stdout和stderr都不是终端时,可通过获取它们文件描述符对应的inode编号和设备编号来判断是否指向同一文件——只有当两者的st_dev(设备编号)和st_ino(inode编号)完全相同时,才说明是同一个文件;否则即为不同文件,触发你需要的输出逻辑。
具体实现步骤
先用
isatty()分别判断stdout(文件描述符1)和stderr(文件描述符2)是否为终端,区分场景:- 一个是终端、另一个是文件:直接触发输出相同消息
- 两者都不是终端:进入文件同一性判断逻辑
- 两者都是终端:不触发输出(不符合你的需求条件)
对非终端的文件描述符,调用
fstat()获取struct stat结构体,对比其中的st_dev和st_ino字段:st_dev:标识文件所在的存储设备st_ino:设备内唯一标识文件的编号
代码示例(C语言)
#include <stdio.h> #include <unistd.h> #include <sys/stat.h> // 判断两个文件描述符是否指向同一文件 int are_same_file(int fd1, int fd2) { struct stat stat1, stat2; if (fstat(fd1, &stat1) == -1 || fstat(fd2, &stat2) == -1) { // 出错时默认视为不同文件,可根据需求调整逻辑 return 0; } return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); } int main() { int stdout_is_tty = isatty(1); int stderr_is_tty = isatty(2); int need_output = 0; // 场景1:一个是终端,另一个是文件 if ((stdout_is_tty && !stderr_is_tty) || (!stdout_is_tty && stderr_is_tty)) { need_output = 1; } // 场景2:两者都是文件且指向不同文件 else if (!stdout_is_tty && !stderr_is_tty) { if (!are_same_file(1, 2)) { need_output = 1; } } if (need_output) { const char *msg = "Message to both stdout and stderr!\n"; write(1, msg, sizeof(msg)-1); write(2, msg, sizeof(msg)-1); } return 0; }
注意事项
- 硬链接:如果两个流指向同一文件的不同硬链接,
fstat返回的st_dev和st_ino会相同,会被判定为同一文件,符合实际逻辑(本质是同一个文件)。 - 符号链接:
fstat会自动跟随符号链接到实际文件,因此即使通过不同符号链接指向同一文件,也会被判定为同一文件。 - 错误处理:若
fstat调用失败(如权限不足),示例中默认视为不同文件,你可根据实际需求调整该逻辑(比如直接退出或输出错误信息)。
内容的提问来源于stack exchange,提问作者def
相关产品推荐
相关产品推荐

