如何将stdout / stderr发送给祖父母进程?

时间:2018-12-22 04:18:44

标签: node.js bash macos shell stdio

我有这个node.js代码:

 const k = cp.spawn('bash');

    k.stdin.end(`

        set -e;
        echo; echo; echo 'du results:';
        ( cd "${extractDir}" && tar -xzvf "${createTarball.pack.value}" ) > /dev/null;
        find "${extractDir}/package" -type f | xargs du --threshold=500KB;

    `);

    k.stdout.pipe(pt(chalk.redBright('this is a big file (>500KB) according to du: '))).pipe(process.stdout);
    k.stderr.pipe(pt(chalk.magenta('du stderr: '))).pipe(process.stderr);

问题是多个孙子孙将把所有的stdout / stderr都写给父母。

我想改成这样:

 const pid = process.pid;

 const k = cp.spawn('bash');

    k.stdin.end(`


        set -e;

        exec 3<>/proc/${pid}/fd/1

        echo > 3 ; echo > 3; echo 'du results:' > 3;

        ( cd "${extractDir}" && tar -xzvf "${createTarball.pack.value}" ) > /dev/null;
        find "${extractDir}/package" -type f | xargs du --threshold=500KB ;

    `);

    k.stdout.pipe(pt(chalk.redBright('this is a big file (>500KB) according to du: '))).pipe(process.stdout);
    k.stderr.pipe(pt(chalk.magenta('du stderr: '))).pipe(process.stderr);

但是该技术不适用于MacOS,因为Mac不具有/ proc / pid fs功能。有人知道我正在尝试做什么,也许是一个好的解决方法?

2 个答案:

答案 0 :(得分:1)

安装Live Example或其他从节点进行原始syscall的方法。然后,以1作为参数进行系统调用libsys,并将结果存储到变量fd中。完成此操作后,fd将是多个文件描述符,该文件描述符是节点标准输出的副本,并且将由子进程继承。此时,只需从bash中删除exec 3<>/proc/${pid}/fd/1,然后用>&3替换所有>&${fd}

答案 1 :(得分:1)

所以我以另一种方式解决了这个问题,OP有点像XY问题-因为我在MacOS上并且没有/proc/<pid>文件,所以我基本上使用mkfifo:

首先我们称之为:

mkfifo "$fifoDir/fifo"

然后我们有

    const fifo = cp.spawn('bash');
    fifo.stdout.setEncoding('utf8');

    fifo.stdout
      .pipe(pt(chalk.yellow.bold('warning: this is a big file (>5KB) according to du: ')))
      .pipe(process.stdout);

    fifo.stdin.end(`

        while true; do
          cat "${fifoDir}/fifo"
        done

    `);

    const k = cp.spawn('bash');

    k.stdin.end(`

        set -e;
        echo; echo 'du results:';
        tar -xzvf "${createTarball.pack.value}" -C "${extractDir}" > /dev/null;
        ${cmd} > "${fifoDir}/fifo";
        kill -INT ${fifo.pid};

    `);

    k.stdout.pipe(process.stdout);
    k.stderr.pipe(pt(chalk.magenta('du stderr: '))).pipe(process.stderr);

    k.once('exit', code => {

      if (code > 0) {
        log.error('Could not run cmd:', cmd);
      }

      cb(code);
    });

  },

“ fifo”子进程是处理k的同级进程,当您查看上述代码块时,这很明显,并且“ fifo”进程最终处理了k进程的一个子进程的标准输出-它们通过命名管道(mkfifo)进行相互通信。