【发布时间】:2021-01-15 07:26:09
【问题描述】:
我有以下代码分叉和执行一个 shell 脚本,并将其 STDERR 和 STDOUT 重定向到父进程。
#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define BUFLEN 65536
int main () {
int pipes[2];
pipe(pipes);
pid_t pid = fork();
if (pid == -1) {return 1;}
else if (pid > 0) {
close(pipes[1]);
char buf[BUFLEN];
size_t n = read(pipes[0], buf, sizeof(buf));
int stat = 0;
waitpid(pid, &stat, 0);
printf("%.*s", n, buf);
} else {
dup2(pipes[1], STDOUT_FILENO);
dup2(pipes[1], STDERR_FILENO);
close(pipes[0]);
char *const argv[] = {"sh", "test", NULL};
execvpe(argv[0], argv, environ);
}
return 0;
}
作为一个最小的工作示例"test"
是:
#!/bin/bash
cat file.txt
echo "Hello!"
echo "Goodbye!"
C 程序的输出是file.txt
的内容,然后回显的输出会丢失。如果是三个 echo 语句,那么它们都会被看到。
我最好的猜测是 echo 是一个内置的 shell,shell 将为cat
分叉,我的管道将丢失。在我的项目中,脚本中调用的第一个命令似乎都丢失了。
如果我的假设是正确的,我如何从 execvpe
产生的任何和所有子级收集所有输出?
【问题讨论】:
-
您需要循环读取直到
read
返回0
(这意味着管道的另一端已关闭)。或者直到出现错误,当然(当read
返回-1
时)。