2016-04-27 4 views
3

Таким образом, я хотел бы сделать следующую командную строку в C:Как труба в C

ps -eo user,pid,ppid 2> log.txt | grep user 2>>log.txt | sort -nk2 > out.txt 

Но я не уверен, как, вообще, как может быть код ... I «Я запутался в том, как мне нужно записать вывод команды в файл, правильный и вывод ошибки ...

Кроме того, я понятия не имею, как я должен структурировать трубопровод и что делать, когда pid == -1 или когда pid> 0 ...

Мой код:

int main(){ 

    int fd0[2], fd1[2], pid0, pid1; 

    pipe(fd0); 
    pid0 = fork(); 
    if (pid == 0){ 
     close(1); 
     dup(fd0[0]); 
     fd_file= open(“./out.txt”, O_WRONLY | O_CREAT | O_TRUNC, 00600); 
     execl("sort","-nk2",">fd_file"); 
     pipe(fd1); 
     pid1 = fork(); 
     if (pid1 == 0){ 
      close(1); 
      dup(fd1[0]); 
      ...? 
     } 

    } 
    else if (pid == -1){ 
     perror("ERROR AT SORT!\n"); 
     exit(1); 
    } 

    return 0; 
} 
+1

Для обработки ошибок лучше всего, вероятно, выйти (с возвратом в 'main()' или 'exit()'). – jdarthenay

+0

Не помещайте новую строку в конце строки, переданной 'perror'. 'perror' будет печатать вашу строку, за которой следует': ', и выглядит странно, если этот двоеточие начинается с новой строки. –

+1

Следующая строка после 'execl' будет выполняться только в случае сбоя' execl'. – cdarke

ответ

1

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

Прочтите комментарии для более подробных объяснений.

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <fcntl.h> 


// Better to use define for constants 
#define SUB_PROCESSES_NUMBER 2 
#define FILE_OUT "out.txt" 
#define FILE_LOGS "log.txt" 

char *command0[] = {"ps", "-eo" "user,pid,ppid", NULL}; 
char *command1[] = {"grep", "^user", NULL}; // "^user" matches lines starting with "user" 
char *command2[] = {"sort", "-nk2", NULL}; 
char **commands[SUB_PROCESSES_NUMBER + 1] = {command0, command1, command2}; 

int main(){ 
    pid_t pid[SUB_PROCESSES_NUMBER]; // good practice: fork() result is pid_t, not int 
    int fd[SUB_PROCESSES_NUMBER][2]; 

    // I recommend opening files now, so if you can't you won't create unecessary processes 
    int fd_file_out = open(FILE_OUT, O_WRONLY | O_CREAT | O_TRUNC, 00600); 
    if (fd_file_out < 0) 
    { 
     perror("open(" FILE_OUT ")"); 
     return 2; 
    } 

    int fd_file_logs = open(FILE_LOGS, O_WRONLY | O_CREAT | O_TRUNC, 00600); 
    if (fd_file_logs < 0) 
    { 
     perror("open(" FILE_LOGS ")"); 
     close(fd_file_out); // Not necessary, but I like to do it explicitly 
     return 2; 
    } 

    for (int i = 0; i < SUB_PROCESSES_NUMBER; i++) // If you decide to add more steps, this loop will be handy 
    { 
     if (pipe(fd[i]) < 0) 
     { 
      perror("pipe"); 
      close(fd_file_out); 
      close(fd_file_logs); 
      if (i > 0) 
      { 
       close(fd[i - 1][0]); 
      } 
      return 2; 
     } 

     pid[i] = fork(); 
     if (pid[i] < 0) 
     { 
      perror("fork()"); 
      close(fd_file_out); 
      close(fd_file_logs); 
      if (i > 0) 
      { 
       close(fd[i - 1][0]); 
      } 
      close(fd[i][0]); 
      close(fd[i][1]); 
      return 2; 
     } 

     if (pid[i] == 0) 
     { 
      close(fd[i][0]); // First thing to do: close pipes and files you don't need any more 
      close(fd_file_out); 

      close(1); 
      dup(fd[i][1]); 
      close(fd[i][1]); // duplicated pipes are not useful any more 

      close(2); // Also need to redirect stderr 
      dup(fd_file_logs); 
      close(fd_file_logs); 

      if (i > 0) 
      { 
       close(0); // Also need to redirect stdin if this is not first process 
       dup(fd[i - 1][0]); 
       close(fd[i - 1][0]); 
      } 

      execvp(commands[i][0], commands[i]); // In a loop, we need a execv()/execvp()/execvpe() call 
      return 2; // Should not be reached; 
     } 

     // sub process either did execvp() or return, he won't reach this point 
     close(fd[i][1]); 
     if (i > 0) 
     { 
      close(fd[i - 1][0]); 
     } 
    } 

    close(fd_file_logs); 

    close(0); 
    dup(fd[SUB_PROCESSES_NUMBER - 1][0]); 
    close(fd[SUB_PROCESSES_NUMBER - 1][0]); 

    close(1); 
    dup(fd_file_out); 
    close(fd_file_out); 

    execvp(commands[SUB_PROCESSES_NUMBER][0], commands[SUB_PROCESSES_NUMBER]); 
    perror("execvp"); 
    return 2; 
} 
Смежные вопросы