Несколько разветвления и распечатка чего-либо перед выполнением - PullRequest
0 голосов
/ 27 сентября 2019
// 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);
  }    
}

У меня есть вышеуказанный код, и я хочу запускать команды сразу (paralel), который находится в массиве команд, и перед каждым запуском хочу напечатать команду.Например;

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*  

Что может бытьпричина и как я могу это исправить?

1 Ответ

1 голос
/ 27 сентября 2019

Вам придется использовать pipe() для создания новых стандартных выходных данных и, необязательно, стандартных дескрипторов файлов ошибок для каждой команды.Затем вы можете прочитать каналы по порядку, пока каждая команда не завершится.

В противном случае, поскольку каждая команда разветвляется в свой собственный процесс, она будет выполняться по своему усмотрению.Вывод текста из команд, выполняющихся одновременно и выдающих вывод на один и тот же терминал, может быть перепутан даже больше, чем показано здесь.

Может быть что-то вроде

#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);
    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);
}

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;
}
...