首页 > 解决方案 > C 使用 execvp 执行带有另一个命令输出的命令

问题描述

我很好地执行诸如“ls”之类的命令和类似的东西,但我想做诸如“ls | sort”之类的事情,但 execvp 系统调用不支持“|”。我怎样才能只使用系统调用来做到这一点?当我尝试类似的东西时

char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg);

它不起作用,我该怎么做?

编辑:

char* execString (char string[]){
int link[2];
pipe(link);

if (fork() == 0){
    int i = 0;
    char *p = strtok(string," ");
    char *x[spacecount(string)+2];

    while(p){
        x[i++] = p;
        p = strtok(NULL," ");
    }
    x[i] = NULL;

    dup2(link[1],1);
    close(link[0]);
    close(link[0]);

    execvp(x[0],x);
    _exit(0);
} else {
    wait(NULL);
    close(link[1]);
    char buf[512];
    int i = 0;

    while (read(link[0],&buf[i++],1) == 1);

    close(link[0]);
    buf[i-2] = '\0';

    return strdup(buf); 
    }
}

这是我正在执行以执行包含命令的字符串的函数,它的返回值是指向包含该命令输出的字符串的指针,我如何使用该输出作为使用 execvp 的新命令的输入或exec 家族的另一个功能?

Edit2:所以我创建了一个新函数,它接收两个字符串作为参数并执行第一个字符串,然后执行第二个字符串,使用第一个 exec 的输出作为输入,我认为它与 ls | 一起工作正常 head -1 和 ls 的其他变体,但是当我执行类似 ls | sort -R 它不起作用,我尝试了几件事,但我不明白为什么会这样,这是代码:

char* execStrings (char previousstring[], char string[]){
int link[2];
pipe(link);

if (fork() == 0){
    int i = 0;
    char *previouscommand[spacecount(previousstring)+2];
    char *temp = strtok(previousstring," ");
    while(temp){
        previouscommand[i++] = temp;
        temp = strtok(NULL," ");
    }
    previouscommand[i] = NULL;

    dup2(link[1],1); /*  stdout result redrecting to write end of pipe */
    close(link[1]);
    close(link[0]);
    execvp(previouscommand[0],previouscommand);

} else {
    wait(NULL);
    int res[2];
    pipe(res);

    if(fork() == 0){
        int i = 0;
        char *temp = strtok(string," ");
        char *command[spacecount(string)+2];

        while(temp){
            command[i++] = temp;
            temp = strtok(NULL," "); 
        }
        command[i] = NULL;

        dup2(link[0],0);
        close(link[0]);
        close(link[1]);

        dup2(res[1],1);
        close(res[1]);
        close(res[0]);

        execvp(command[0],command)
    } else {
        wait(NULL);

        close(res[1]);
        char buf[512];
        int i = 0;

        while (read(res[0],&buf[i++],1) == 1);

        close(res[0]);
        buf[i-2] = '\0';

        return strdup(buf);
    }
}
}

标签: cunixpipe

解决方案


你想做一些类似的事情,ls | sort但你做的方式喜欢

char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg); /*it won't work */

将不起作用,因为您在这里调用execvp并且lssort是两个独立的进程而不是单个进程。还

ls     |    sort  => output of process-1 make as input to process-2 & execute it   
|            |
process-1  process-2

为了实现上述创建两个进程,通过调用fork()和使用exec()family函数来替换lssort在子进程和父进程中。

这是示例代码

int main(void) {
        int p[2];
        pipe(p);
        char *arg[] = {"ls","sort",NULL};
        if(fork()==0) {
                close(0);/* close the stdin stream so that this 
process shoulbn't read from stdin */
                dup(p[0]);/* read from read end of pipe */
                close(p[1]);
                execlp(arg[1],arg[1],(char*)NULL);
        }
        else{
                close(1);/* close the stdout stream, so that o/p shouldn't print on monitor */
                dup(p[1]); /*  stdout result redrecting to write end of pipe */
                close(p[0]);
                execlp(arg[0],arg[0],(char*)NULL);
        }
        return 0;
}

推荐阅读