You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C语言编写程序将终端输出记录到文本文件中?

自动记录终端输出的C语言实现方案

要实现终端输出自动保存到文件,同时保留实时终端显示,核心是捕获shell的标准输出(stdout)和标准错误(stderr),并将内容同时写入终端和日志文件。以下是纯C语言实现的方案,适合用来练习系统调用和进程控制。

实现思路

  1. 生成按日期命名的日志文件,方便按天查找历史记录
  2. 通过管道(pipe)实现父进程与子进程(shell)的通信
  3. 子进程将stdout和stderr重定向到管道写端
  4. 父进程从管道读端读取内容,同时写入终端和日志文件
  5. 用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;
}

编译与使用

  1. 编译代码:
    gcc terminal_logger.c -o terminal_logger
    
  2. 启动日志shell:
    ./terminal_logger
    
    此时会打开一个新的shell会话,所有命令的输出会同时显示在终端,并写入当天的日志文件(如terminal_log_20240520.txt)。
  3. 自动启动:
    如果希望每次打开终端都自动启用日志功能,可将启动命令添加到shell配置文件中:
    • Bash:编辑~/.bashrc,添加~/path/to/terminal_logger
    • Zsh:编辑~/.zshrc,添加相同内容

细节说明

  • 日志按日期命名,直接通过文件名就能定位到昨天的记录
  • 合并记录stdout和stderr,还原终端实际输出效果
  • 每个系统调用都做了错误检查,便于调试时排查问题
  • 可修改/bin/bash为你的默认shell路径(如/bin/zsh)

内容的提问来源于stack exchange,提问作者Anthonzie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:20:51