c - 多次 fork 并在 exec 之前打印一些内容

标签 c shell process fork

// I have commands in commands[] array
pid_t pid[command_count];

for (int i = 0; i < command_count; i++) {
  if ((pid[i]=fork()) == 0) {
      printf("--%s\n", commands[i][0]);
      execvp(commands[i][0],commands[i]);
      _exit(1);
  }
  if (pid[i] < 0) {

  }
}

for (i = 0; i < command_count; i++) { 
  if (pid[i] > 0) {
    int status;
    waitpid(pid[i], &status, 0);
  }    
}

我有上面的代码,想要立即(并行)运行命令数组中的命令,并且在每次运行之前,想要打印命令。例如;

ls | pwd | ls -a

它应该在命令运行之前打印每个命令名称

--ls
.. a b.txt
--pwd
/a/a/
--ls -a
*some output*

但它打印如下

--ls
--pwd
--ls -a
.. a b.txt
*some directory as a result of pwd*
*some output*  

可能是什么原因以及如何解决它?

最佳答案

您必须使用pipe()为每个命令创建新的标准输出和可选的标准错误文件描述符。然后您可以按顺序读取管道,直到每个命令完成。

否则,因为每个命令都被 fork 到自己的进程中,所以它将在自己方便的时候运行。同时运行所有命令并向同一终端生成输出的文本输出可能会比此处显示的更加困惑。

也许是这样的

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

struct cmd_data {
    const char *cmd;
    int fd[2];  // stdout pipe for command
    pid_t pid;
    int status; // exit status
};

void cmd_launch(struct cmd_data *p, const char *cmd) {
    int r;

    p->cmd = cmd;
    r = pipe(p->fd);
    if(r<0) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    r = fork();
    if(r < 0) {
        perror("fork");
        close(p->fd[0]);
        close(p->fd[1]);
    } else if( r > 0 ) {
        p->pid = r;
        close(p->fd[1]);
    } else {
        close(p->fd[0]);
        dup2(p->fd[1], STDOUT_FILENO);
        close(p->fd[1]);
        r = execlp(cmd, cmd, NULL);
        perror("execlp");
        exit(EXIT_FAILURE);
    }
}

void cmd_join(struct cmd_data *p) {
    char buf[4096];
    const size_t buflen = sizeof buf;
    ssize_t bytes;

    printf("-- %s\n", p->cmd);
    fflush(stdout);
    while( 0 != (bytes = read(p->fd[0], buf, buflen)) ) {
        write(STDOUT_FILENO, buf, bytes);
    }
    close(p->fd[0]);
    pid_t r = waitpid(p->pid, &p->status, 0);
    if(r<0){
        perror("waitpid");
    }
    printf("-- completed with status %d\n", p->status);
    fflush(stdout);
}

int main(int argc, char *argv[]) {
    size_t cmd_c = argc - 1;
    struct cmd_data *p = calloc(argc, sizeof *p);
    size_t i;

    for(i = 0; i < cmd_c; ++i) {
        cmd_launch(p + i, argv[i + 1]);
    }

    for(i = 0; i < cmd_c; ++i) {
        cmd_join(p + i);
    }

    free(p);
    return EXIT_SUCCESS;
}

关于c - 多次 fork 并在 exec 之前打印一些内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58140268/

相关文章:

c - 在 debugfs 中实现读取操作列表

git - 如何让 bash 补全与别名一起使用?

linux - 以编程方式获取另一个进程的父 pid?

Java - 运行 7zip

mysql - 如何判断一个MySQL进程是否卡住了?

c++ - 这个宏如何工作?

c - 在Infiniband中,PCIe-BAR、Infiniband卡的内部缓冲区或远程计算机的RAM中有什么映射?

c - 如何在c89中定义浮点 double 常量

shell - Pentaho 通用错误处理脚本

linux - 查找,grep gzipped 文件