如何用C语言编写程序将终端输出记录到文本文件中?
自动记录终端输出的C语言实现方案
要实现终端输出自动保存到文件,同时保留实时终端显示,核心是捕获shell的标准输出(stdout)和标准错误(stderr),并将内容同时写入终端和日志文件。以下是纯C语言实现的方案,适合用来练习系统调用和进程控制。
实现思路
- 生成按日期命名的日志文件,方便按天查找历史记录
- 通过管道(pipe)实现父进程与子进程(shell)的通信
- 子进程将stdout和stderr重定向到管道写端
- 父进程从管道读端读取内容,同时写入终端和日志文件
- 用
fork()+execvp()启动shell,保证正常的终端交互体验
完整代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/wait.h> #include <time.h> #include <string.h> #define LOG_FILE_FORMAT "terminal_log_%Y%m%d.txt" int main() { // 生成带日期的日志文件名 char log_filename[64]; time_t now = time(NULL); strftime(log_filename, sizeof(log_filename), LOG_FILE_FORMAT, localtime(&now)); // 打开日志文件(追加模式,不存在则创建,权限644) int log_fd = open(log_filename, O_WRONLY | O_CREAT | O_APPEND, 0644); if (log_fd == -1) { perror("open log file failed"); exit(EXIT_FAILURE); } // 创建管道,用于子进程输出传递给父进程 int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe failed"); close(log_fd); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork failed"); close(pipefd[0]); close(pipefd[1]); close(log_fd); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程:启动shell,重定向输出到管道 close(pipefd[0]); // 关闭管道读端 // 将stdout和stderr都指向管道写端 dup2(pipefd[1], STDOUT_FILENO); dup2(pipefd[1], STDERR_FILENO); close(pipefd[1]); // 原始写端可关闭 // 启动默认shell(这里用bash,可根据需求改为zsh等) char *shell_args[] = {"/bin/bash", NULL}; execvp(shell_args[0], shell_args); // execvp失败才会执行到这里 perror("exec shell failed"); exit(EXIT_FAILURE); } else { // 父进程:读取管道内容,同时写入终端和日志 close(pipefd[1]); // 关闭管道写端 // 保存终端的原始stdout描述符,用于输出到屏幕 int term_stdout = dup(STDOUT_FILENO); if (term_stdout == -1) { perror("dup terminal stdout failed"); close(pipefd[0]); close(log_fd); exit(EXIT_FAILURE); } char buffer[1024]; ssize_t bytes_read; // 循环读取管道数据,直到子进程退出 while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer))) > 0) { write(term_stdout, buffer, bytes_read); // 输出到终端 write(log_fd, buffer, bytes_read); // 写入日志文件 } // 等待子进程结束 wait(NULL); // 清理资源 close(pipefd[0]); close(log_fd); close(term_stdout); } return EXIT_SUCCESS; }
编译与使用
- 编译代码:
gcc terminal_logger.c -o terminal_logger - 启动日志shell:
此时会打开一个新的shell会话,所有命令的输出会同时显示在终端,并写入当天的日志文件(如./terminal_loggerterminal_log_20240520.txt)。 - 自动启动:
如果希望每次打开终端都自动启用日志功能,可将启动命令添加到shell配置文件中:- Bash:编辑
~/.bashrc,添加~/path/to/terminal_logger - Zsh:编辑
~/.zshrc,添加相同内容
- Bash:编辑
细节说明
- 日志按日期命名,直接通过文件名就能定位到昨天的记录
- 合并记录stdout和stderr,还原终端实际输出效果
- 每个系统调用都做了错误检查,便于调试时排查问题
- 可修改
/bin/bash为你的默认shell路径(如/bin/zsh)
内容的提问来源于stack exchange,提问作者Anthonzie
相关产品推荐
相关产品推荐

