C - 将 awk/sed 标准输出重定向到管道不起作用
C - Redirecting awk/sed stdout to pipe doesn't work
所以我有一个练习要做,这个练习的一部分要求我们执行作为参数传递的命令,能够在 stdin 上传递一些字符串,并在 stdout 和 stderr 上获得它的输出。
我是怎么做到的,我需要将 stdout 和 stderr(属于 child,将调用 exec)重定向到几个管道(管道的另一端由 parent 保持打开状态).
我设法做到了,当我要求它执行 bash 并向它发送“ls”时,它给了我我想要的,在我想要的地方。猫和其他人也一样。
问题是,当我尝试执行 awk 或 sed 时,管道上什么也没有写。曾经。
如果我保持标准输出不变,它会按应有的方式打印出来。但是一旦我重定向标准输出,就什么也没有了。
我什么都试过了,select(), wait(), sleep()(尽管这是不允许的)。似乎没有任何效果。
我举了一个最基本的工作示例来说明我的意思(显然,它缺乏约定俗成和用心写作,如 free() 和 close(),但它确实起作用了),这就是我要附加的示例。当我这样称呼它时,代码有效:
./program $(which bash)
它提示一些东西,我写“ls”,它给了我预期的结果
但是当我尝试
./program $(which awk) '{print [=13=];}'
我一无所获
这是代码(最小工作示例):
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
int main(int argc, char* argv[]){
int fdStdinP[2],fdStdoutP[2];
char *string,*array[3];
array[0]=argv[1];
array[1]=argv[2];
array[2]=0;
pipe(fdStdinP);
pipe(fdStdoutP);
int pid=fork();
if(pid==0){
close(fdStdinP[1]);
close(fdStdoutP[0]);
dup2(fdStdinP[0],0);
close(fdStdinP[0]);
dup2(fdStdoutP[1],1);
close(fdStdoutP[1]);
//as suggested, the file descriptors are now closed
execvp(argv[1],array);
perror("");
return 0;
}
close(fdStdinP[0]);
close(fdStdoutP[1];
string=calloc(1024,sizeof(char));
read(0,string,1024);
write(fdStdinP[1],string,1024);
free(string);
string=calloc(1024,sizeof(char));
read(fdStdoutP[0],string,1024);
printf("I have read:%s",string);
return 0;
}
感谢您的宝贵时间。
Awk 继续等待输入并缓冲其输出,因此似乎挂起。关闭发送端将告诉 awk 它的输入已结束,以便它结束并刷新其输出。
write(fdStdinP[1],string,1024);
close(fdStdinP[1]); // just added this line.
所以我有一个练习要做,这个练习的一部分要求我们执行作为参数传递的命令,能够在 stdin 上传递一些字符串,并在 stdout 和 stderr 上获得它的输出。 我是怎么做到的,我需要将 stdout 和 stderr(属于 child,将调用 exec)重定向到几个管道(管道的另一端由 parent 保持打开状态). 我设法做到了,当我要求它执行 bash 并向它发送“ls”时,它给了我我想要的,在我想要的地方。猫和其他人也一样。 问题是,当我尝试执行 awk 或 sed 时,管道上什么也没有写。曾经。 如果我保持标准输出不变,它会按应有的方式打印出来。但是一旦我重定向标准输出,就什么也没有了。 我什么都试过了,select(), wait(), sleep()(尽管这是不允许的)。似乎没有任何效果。
我举了一个最基本的工作示例来说明我的意思(显然,它缺乏约定俗成和用心写作,如 free() 和 close(),但它确实起作用了),这就是我要附加的示例。当我这样称呼它时,代码有效:
./program $(which bash)
它提示一些东西,我写“ls”,它给了我预期的结果
但是当我尝试
./program $(which awk) '{print [=13=];}'
我一无所获
这是代码(最小工作示例):
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
int main(int argc, char* argv[]){
int fdStdinP[2],fdStdoutP[2];
char *string,*array[3];
array[0]=argv[1];
array[1]=argv[2];
array[2]=0;
pipe(fdStdinP);
pipe(fdStdoutP);
int pid=fork();
if(pid==0){
close(fdStdinP[1]);
close(fdStdoutP[0]);
dup2(fdStdinP[0],0);
close(fdStdinP[0]);
dup2(fdStdoutP[1],1);
close(fdStdoutP[1]);
//as suggested, the file descriptors are now closed
execvp(argv[1],array);
perror("");
return 0;
}
close(fdStdinP[0]);
close(fdStdoutP[1];
string=calloc(1024,sizeof(char));
read(0,string,1024);
write(fdStdinP[1],string,1024);
free(string);
string=calloc(1024,sizeof(char));
read(fdStdoutP[0],string,1024);
printf("I have read:%s",string);
return 0;
}
感谢您的宝贵时间。
Awk 继续等待输入并缓冲其输出,因此似乎挂起。关闭发送端将告诉 awk 它的输入已结束,以便它结束并刷新其输出。
write(fdStdinP[1],string,1024);
close(fdStdinP[1]); // just added this line.