为何自定义tee.c程序与系统tee命令输出存在差异?
问题原因分析与排查方案
核心原因推测
你遇到的问题大概率是代码对命令行参数的处理逻辑错误,再加上文件写入流程存在疏漏,具体表现为:
- 错误地将命令行传入的文件名(
test.txt)当作输出内容打印到终端,而非将其作为目标文件路径去打开写入。 - 没有正确读取标准输入(
stdin)的内容,自然也就无法将ls -l的输出写入文件,导致文件大小为0。
常见错误点拆解
1. 命令行参数解析错误
系统tee的逻辑是:跳过程序名(argv[0]),将后续第一个参数作为输出文件路径,然后从stdin读取数据并同时输出到终端和文件。
如果你的实现代码没有做参数判断(比如没检查argc >= 2),或者错误地遍历输出了argv数组的所有内容,就会把test.txt打印到终端,同时根本没去打开这个文件写入数据。
2. 文件打开与写入逻辑错误
- 打开模式错误:比如用了
O_RDONLY(只读)模式打开文件,后续写入操作会直接失败;或者没有添加O_CREAT和O_TRUNC参数,导致文件无法创建或清空原有内容。 - 写入流程缺失:代码可能只实现了向终端(
stdout)输出,完全没处理文件写入;或者读取stdin的逻辑有问题(比如只读取一次就退出,没循环到EOF)。
3. 错误处理缺失
很多实现会忽略系统调用的返回值检查,比如open返回-1(文件打开失败)、read/write返回值不等于预期字节数时,没有报错就继续执行,导致问题被隐藏。
排查与修复步骤
检查参数解析代码
确认代码中是否正确提取了目标文件名:- 必须判断
argc >= 2,否则提示用法错误(比如Usage: ./tee filename)。 - 用
argv[1]作为文件路径,而非遍历输出所有argv元素。
- 必须判断
验证文件打开逻辑
如果用系统调用,确保打开文件的参数正确:int fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);O_WRONLY:以只写模式打开O_CREAT:文件不存在则创建O_TRUNC:文件存在则清空内容0644:设置文件权限为所有者读写,其他用户只读
确认读写循环逻辑
必须循环读取stdin直到EOF(read返回0),同时将读取到的数据分别写入stdout和目标文件:char buf[1024]; ssize_t n; while ((n = read(STDIN_FILENO, buf, sizeof(buf))) > 0) { write(STDOUT_FILENO, buf, n); // 输出到终端 write(fd, buf, n); // 写入文件 }注意要检查
read/write的返回值,处理错误情况。添加错误提示
在open、read、write、close调用失败时,向stderr输出错误信息,方便定位问题。
示例正确实现片段
以下是一个简化的符合预期的tee实现(基于系统调用):
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #define BUF_SIZE 1024 int main(int argc, char *argv[]) { int fd; ssize_t numRead; char buf[BUF_SIZE]; if (argc != 2) { const char *errMsg = "Usage: ./tee filename\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { const char *errMsg = "Failed to open target file\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) { if (write(STDOUT_FILENO, buf, numRead) != numRead) { const char *errMsg = "Error writing to stdout\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } if (write(fd, buf, numRead) != numRead) { const char *errMsg = "Error writing to file\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } } if (numRead == -1) { const char *errMsg = "Error reading from stdin\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } if (close(fd) == -1) { const char *errMsg = "Error closing file\n"; write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
内容的提问来源于stack exchange,提问作者Chih-Hao Liu
相关产品推荐
相关产品推荐

