You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现支持多管道命令的简易Shell出现阻塞及tr命令兼容问题求助

简易Shell管道阻塞与tr命令兼容问题求助

我编写了一段C语言代码,试图实现一个支持多管道命令的简易Shell。该Shell执行单条命令时功能正常,但执行带管道的命令时会出现阻塞情况。调试时无法命中断点子进程内的断点,怀疑是管道关闭逻辑存在问题,但不确定具体原因,耗时数小时仍未解决。另外发现该Shell也无法正常兼容tr命令。

以下是相关代码:

void executefork(char **commands, int num_commands, int input_fd) {
    if (num_commands == 0) {
        return;
    }

    int pipefd[2];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        return;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        if (num_commands > 1) {
            if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
                perror("dup2");
                exit(EXIT_FAILURE);
            }
        }

        if (input_fd != STDIN_FILENO) {
            if (dup2(input_fd, STDIN_FILENO) == -1) {
                perror("dup2");
                exit(EXIT_FAILURE);
            }
        }

        close(pipefd[0]);
        close(pipefd[1]);
        
        execute(commands[0]);

    } else {
        close(pipefd[1]);

        if (num_commands > 1) {
            printf("\nReached");
            executefork(commands + 1, num_commands - 1, pipefd[0]);
        }
        close(pipefd[0]);
        int status;
        if (waitpid(pid, &status, 0) == -1) {
            perror("waitpid");
            exit(EXIT_FAILURE);
        }
    }
}

int main(int argc, char *argv[]) {
    size_t len = 1024;
    ssize_t cha;
    char *line = (char *) malloc(len);
    
    char *pipeCmd[strlen(line)];

    while (1) {
        printf("sish> ");
        cha = getline(&line, &len, stdin);
        if (cha == -1 || cha == 0) {
            continue;
        }
        line[strcspn(line, "\n")] = '\0';
        if (line[0] == '\0') {
            continue;
        }

        char *copy = strdup(line);
        char *com = strtok(copy, "|");
        int index = 0;
        while (com != NULL) {
            pipeCmd[index++] = com;
            addHistory(com);
            com = strtok(NULL, "|");
        }
        pipeCmd[index] = NULL;

        executefork(pipeCmd, index, STDIN_FILENO);

        if (flag == 1) {
            break;
        }
    }

    free(line);
    return 0;
}

void execute(char *phrase) {
    char *va = strdup(phrase);
    char *token = strtok(strdup(va), " ");

    if (strcmp(token, "history") == 0) {
        history(phrase);
        return;
    } else if (strcmp(token, "exit") == 0) {
        flag = 1;
        return;
    } else if (strcmp(token, "cd") == 0) {
        changeDir(phrase);
        return;
    } else {
        pid_t cpid;
        cpid = fork();
        if (cpid < 0) {
            perror("fork error");
            exit(-1);
        }
        if (cpid == 0) {
            char *pass[sizeof(phrase) / sizeof(char *) + 1];
            int i = 0;
            while (token != NULL && i < sizeof(pass) / sizeof(char*)) {
                pass[i++] = token;
                token = strtok(NULL, " ");
            }
            pass[i] = NULL;
            execvp(pass[0], pass);
            perror("execvp failed");
            exit(EXIT_FAILURE);
        } else {
            waitpid(cpid, NULL, 0);
        }
    }
}

测试案例1:管道命令阻塞

sish> cat pi.txt //此部分正常
Hello people, Run debug save share stop download languages
sish> cat pi.txt | grep the //此命令持续阻塞

测试案例2:tr命令兼容问题

sish> echo "Hi how are you" | tr h w
tr: missing operand after ‘h’
Two strings must be given when translating.
Try 'tr --help' for more information.
waitpid: No child processes

内容的提问来源于stack exchange,提问作者Pranjal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:47:18