调用execvp()的内部重定向不起作用

调用execvp()的内部重定向不起作用,c,exec,fork,io-redirection,C,Exec,Fork,Io Redirection,我一直在使用execvp()实现一个执行给定命令的小程序。如果不使用重定向,但在运行以下命令时,它可以正常工作: cat file1.txt > redirected.txt cat输出以下错误消息并失败: cat: >: No such file or directory cat: redirected.txt: No such file or directory 我已经做了一些深入的研究,我开始认为也许execvp()不允许执行重定向,因为它不在shell中运行。这是否意味着

我一直在使用execvp()实现一个执行给定命令的小程序。如果不使用重定向,但在运行以下命令时,它可以正常工作:

cat file1.txt > redirected.txt
cat输出以下错误消息并失败:

cat: >: No such file or directory
cat: redirected.txt: No such file or directory
我已经做了一些深入的研究,我开始认为也许execvp()不允许执行重定向,因为它不在shell中运行。这是否意味着我必须手动选择何时发生重定向,并在fork/exec代码中使用管道来绕过此限制?有没有比使用execvp()更好的方法

谢谢

您的“执行给定命令的小程序”本质上是一个shell。因为您正在编写shell,所以您的工作就是使用所需的任何语法实现重定向。
重定向操作符不是内核的功能,而是shell功能

要实现
sh
样式的重定向,必须解析命令,找到重定向操作符,打开文件并将其分配给输入/输出描述符。这必须在调用
execvp
之前完成。查找
dup2
系统调用。

如果您确实想使用那种语法,可以使用system()。正如您所注意到的,重定向和通配符扩展以及一大堆其他事情都是由类Unix系统上的shell处理的

使用fork的方法如下所示:

int kidpid;
int fd = open("redirected.txt", O_WRONLY|O_TRUNC|O_CREAT, 0644);
if (fd < 0) { perror("open"); abort(); }
switch (kidpid = fork()) {
  case -1: perror("fork"); abort();
  case 0:
    if (dup2(fd, 1) < 0) { perror("dup2"); abort(); }
    close(fd);
    execvp(cmd, args); perror("execvp"); abort();
  default:
    close(fd);
    /* do whatever the parent wants to do. */
}
int-kidpid;
int fd=open(“redirected.txt”,O|WRONLY | O|TRUNC | O|u CREAT,0644);
如果(fd<0){perror(“open”);abort();}
开关(kidpid=fork()){
案例1:perror(“fork”);abort();
案例0:
if(dup2(fd,1)<0){perror(“dup2”);abort();}
关闭(fd);
execvp(cmd,args);perror(“execvp”);abort();
违约:
关闭(fd);
/*做父母想做的事*/
}

看起来最简单的方法是:

execlp( "/bin/sh", "/bin/sh", "-c", "cat file1.txt > redirected.txt", (char *)NULL );

您可以对
execvp

执行相同的操作,可以在命令中的“cat”之前添加“exec”,以避免有额外的进程。OP的赋值可能需要使用
execvp
(而不是高级
系统
),以避免出于教育目的使用shell您应该关闭
fd
(或设置其close-on-exec标志)。目前,进程会获得一个额外的打开文件描述符。在这里危害不大,但在其他情况下可能是个问题。@JonathanLeffler:抓得好。最后我删除了错误注释,在子项中添加了close(),并修复了dup2()上的错误检查。