【问题标题】:Duplicate stdout and stderr from fork process to files将 fork 进程中的 stdout 和 stderr 复制到文件中
【发布时间】:2014-12-04 13:10:39
【问题描述】:

我需要将子进程的stdoutstderr 复制到多个文件中。
我知道我可以使用tee(),但我还没有找到这方面的例子。 现在,只需将所有内容打印到 stdout 和 stderr。 怎么做?

 pid_t childId = fork();
    switch(childId){
    case -1:
        perror("fork() error!\n");
        return;
    case 0:

        mysignal(SIGTTOU, SIG_DFL);
        mysignal(SIGTTIN, SIG_DFL);
        mysignal(SIGCHLD, SIG_DFL);
        if(!background)
            tcsetpgrp(cterm, getpid());
        setpgid(0, 0);
        if (isWriter) close(pipefd[0]);
        if (isReader!=-1) {
            close(0);
            dup(oldChannelOut);
        }

        if(isWriter){
            close(1);
            dup(pipefd[1]);
        }
        //exec, if program is in current directory
        execv(commandArgv[0], commandArgv);
        int i = 0;
        char buf[_POSIX_MAX_PATH];
        while(path[i] != NULL){
            buf[0] = '\0';
            strcat(buf, path[i]);
            if(path[i][ strlen(path[i])-1 ] != '/'){
                buf[strlen(path[i])] = '/';
                buf[strlen(path[i])+1] = '\0';
            }
            strcat(buf, commandArgv[0]);
            execv(buf, commandArgv);
            ++i;
        }
        fprintf(stderr,"\"%s\": command not found\n",commandArgv[0]);
        exit(1);

UPD:尝试修改后,不工作。问题出在哪里?

fdout=open("1", O_APPEND | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
fderr=open("2",O_APPEND | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
...
case 0:
if (isReader!=-1) {
close(0);
dup(oldChannelOut);
}
dup2(fdout, 1);
dup2(fderr, 2);
close(fdout);
close(fderr);
 exec....
default:
{

if(background) {
addJob(&jobListStartB,childId,commandArgv,BACKGROUND);
if (oldChannelOut != -1){
close(oldChannelOut);
oldChannelOut = -1;
}
}
else if(!background){
if (oldChannelOut != -1){

close(oldChannelOut);
oldChannelOut = -1;
}
} 

【问题讨论】:

  • 那么,fork 进程的stdout 和stderr 应该写入stdout 和stderr 以及两个文件吧?
  • 它们必须复制到两个文件,不能只写。
  • 那是什么意思?
  • stderr/stdout 到文件 AND 到 stderr/stdout

标签: c linux stdout system-calls


【解决方案1】:

使用teesplice将数据从一个句柄写入多个其他句柄:

// Needs at least two targets, sentinel is INVALID_HANDLE_VALUE
int push_to_all(int source, ssize_t count, ...) {
    va_list vl;
    va_start(vl, count);
    int target = va_arg(vl, int), next = va_arg(vl, int);
    count = tee(source, target, count, SPLICE_F_NONBLOCK);
    if(count <= 0) { va_end(vl); return count; }
    while((target = next, next = va_arg(vl, int)) > 0) {
        tee(source, target, count, 0);
    va_end(vl);
    return splice(source, 0, target, 0, count, 0);
}

【讨论】:

  • 这是一个从管道读取到您的子进程并将该数据写入任意数量的其他句柄的函数。
猜你喜欢
  • 2011-04-22
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
相关资源
最近更新 更多