如何将所有stdio记录并代理到子流程?

时间:2016-02-12 01:17:20

标签: stdio

我有两个过程,父母和孩子。父进程执行子进程并使用stdin / out来通信和控制子进程。

我想通过记录它们之间发生的所有io(stdin,out,err)来检查这两个进程之间使用的协议。

我能够指定父进程执行以启动子进程的命令,所以我的问题是:

是否有命令行工具和/或简单的C / Java / python程序可以“包装”子命令并记录(到文件)所有stdin + stdout,同时还在它们之间转发所有io(所以子过程继续工作?)

从图形上看,我的想法是:

目前:Parent <-io-> Child

想法:Parent <-io-> Wrapper/Proxy <-io-> Child

提前致谢!

1 个答案:

答案 0 :(得分:0)

它不漂亮,但它奏效了。它没有很好地关闭,但它允许我通过使用我自己的可执行文件包装子进程命令来检查父进程和子进程之间的通信:

概述:

  • 它希望子命令(及其参数)作为包装器参数
  • 设置3个管道以重新路由+拦截std {in,out,err}
  • 它在内部多次分配一个进程来使用和记录每个stdio流
  • 写出文件stdin.logstdout.logstderr.log
  • 最终分叉预期的可执行文件,设置截获的stdio管道

用法:./wrapper /bin/othercommand -a -b -c

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

int ioin[2];
int ioout[2];
int ioerr[2];

void handler(int sig)
{
    printf("Closing everything!\n");

    close(ioin[0]);
    close(ioin[1]);
    close(ioout[0]);
    close(ioout[1]);
    close(ioerr[0]);
    close(ioerr[1]);
}

int main(int argc, const char * argv[]) {
    pipe(ioin);
    pipe(ioout);
    pipe(ioerr);

    // execvp(argv[1], argv+1);

    signal(SIGHUP, &handler);

    if(fork() == 0)
    {
        close(ioin[0]); // close in read
        close(ioout[1]); // close in write
        close(ioerr[1]); // close in write

        if(fork() == 0)
        {
            if(fork() == 0)
            {
                char buf;
                FILE* f = fopen("stdin.log", "w+");
                // fprintf(f, "%d\n", getpid());
                // fflush(f);
                while (read(STDIN_FILENO, &buf, 1) > 0) {
                    write(ioin[1], &buf, 1);
                    fwrite(&buf, 1, 1, f);
                    fflush(f);
                }
                fprintf(f, "Done\n");

                fclose(f);
                close(ioin[1]);
                close(0);

                kill(0, SIGHUP);

                _exit(0);
            }
            else
            {
                char buf;
                FILE* f = fopen("stdout.log", "w+");
                // fprintf(f, "%d\n", getpid());
                // fflush(f);
                while (read(ioout[0], &buf, 1) > 0) {
                    write(STDOUT_FILENO, &buf, 1);
                    fwrite(&buf, 1, 1, f);
                    fflush(f);
                }
                fprintf(f, "Done\n");

                fclose(f);
                close(ioout[0]);
                _exit(0);
            }
        }
        else
        {
            char buf;
            FILE* f = fopen("stderr.log", "w+");
            // fprintf(f, "%d\n", getpid());
            // fflush(f);
            while (read(ioerr[0], &buf, 1) > 0) {
                write(STDERR_FILENO, &buf, 1);
                fwrite(&buf, 1, 1, f);
                fflush(f);
            }
            fprintf(f, "Done\n");


            fclose(f);
            close(ioerr[0]);
            _exit(0);
        }
    }
    else
    {
        close(ioin[1]); // close in write
        close(ioout[0]); // close in read
        close(ioerr[0]); // close in read

        if(fork() == 0)
        {
            close(0);
            dup(ioin[0]);

            close(1);
            dup(ioout[1]);

            close(2);
            dup(ioerr[1]);

            execvp(argv[1], argv+1);
        }
        else
        {
            wait(NULL);
        }
    }
}

我很高兴接受另一个更清洁和/或更正确的答案。