programing

exec에서 출력 잡기

muds 2023. 11. 7. 21:10
반응형

exec에서 출력 잡기

명령어 출력을 잡는 C 프로그램을 작성하려고 하는데 다른 프로그램으로 전달하겠습니다.

문제가 있어서 명령어 출력 및 저장 방법을 찾을 수 없습니다.아래는 제가 가지고 있는 것의 샘플입니다.

if(fork() == 0){
   execl("/bin/ls", "ls", "-1", (char *)0);
   /* do something with the output here */
}
else{
    //*other stuff goes here*
}

그래서 기본적으로 "execl"에서 출력을 얻어 다른 것(예를 들어 일종의 버퍼에 저장)으로 전달할 수 있는 방법이 있는지 궁금합니다.

좋은 제안이 있겠습니다.

상위 프로세스에서 하위 프로세스로 파이프를 생성해야 합니다.pipe(). 그런 다음 리디렉션해야 합니다.standard ouput(STDOUT_FILENO) 및error output(STDERR_FILENO) 사용dup아니면dup2파이프에, 그리고 부모 프로세스에서, 파이프에서 읽습니다.그건 작동할 거야.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);

int main() {
  int link[2];
  pid_t pid;
  char foo[4096];

  if (pipe(link)==-1)
    die("pipe");

  if ((pid = fork()) == -1)
    die("fork");

  if(pid == 0) {

    dup2 (link[1], STDOUT_FILENO);
    close(link[0]);
    close(link[1]);
    execl("/bin/ls", "ls", "-1", (char *)0);
    die("execl");

  } else {

    close(link[1]);
    int nbytes = read(link[0], foo, sizeof(foo));
    printf("Output: (%.*s)\n", nbytes, foo);
    wait(NULL);

  }
  return 0;
}

파이프를 열고 그 파이프에 맞게 stdout을 바꿉니다.

 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>

 int pipes[2];

 pipe(pipes); // Create the pipes

 dup2(pipes[1],1); // Set the pipe up to standard output

그 후 stdout으로 가는 모든 것(예: printf)이 파이프[0]에서 나옵니다.

FILE *input = fdopen(pipes[0],"r");

이제 일반 파일 설명자처럼 출력을 읽을 수 있습니다.자세한 내용은 이 을 참조하십시오.

조나단 레플러에게 감사드리며, 한 번만 모든 응답을 읽을 수 없기 때문에 위 코드를 최적화합니다.

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

#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);

int main() {
  int link[2];
  pid_t pid;
  char foo[4096 + 1];
  memset(foo, 0, 4096);

  if (pipe(link)==-1)
    die("pipe");

   if ((pid = fork()) == -1)
    die("fork");

  if(pid == 0) {

    dup2 (link[1], STDOUT_FILENO);
    close(link[0]);
    close(link[1]);
    execl("/bin/ls", "ls", "-1", (char *)0);
    die("execl");
  } else {
    close(link[1]);
    int nbytes = 0;
    std::string totalStr;
    while(0 != (nbytes = read(link[0], foo, sizeof(foo)))) {
        totalStr = totalStr + foo;
        printf("Output: (%.*s)\n", nbytes, foo);
        memset(foo, 0, 4096);
    }
    wait(NULL);
  }
  return 0;
}

문자열(char *)로 출력하려면 다음 옵션이 있습니다(최소한 Linux의 경우).

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

char* qx(char** cmd, int inc_stderr) {
  int stdout_fds[2];
  pipe(stdout_fds);

  int stderr_fds[2];
  if (!inc_stderr) {
    pipe(stderr_fds);
  }

  const pid_t pid = fork();
  if (!pid) {
    close(stdout_fds[0]);
    dup2(stdout_fds[1], 1);
    if (inc_stderr) {
      dup2(stdout_fds[1], 2);
    }

    close(stdout_fds[1]);

    if (!inc_stderr) {
      close(stderr_fds[0]);
      dup2(stderr_fds[1], 2);
      close(stderr_fds[1]);
    }

    execvp(*cmd, cmd);
    exit(0);
  }

  close(stdout_fds[1]);

  const int buf_size = 4096;
  char* out = malloc(buf_size);
  int out_size = buf_size;
  int i = 0;
  do {
    const ssize_t r = read(stdout_fds[0], &out[i], buf_size);
    if (r > 0) {
      i += r;
    }

    if (out_size - i <= 4096) {
      out_size *= 2;
      out = realloc(out, out_size);
    }
  } while (errno == EAGAIN || errno == EINTR);

  close(stdout_fds[0]);

  if (!inc_stderr) {
    close(stderr_fds[1]);
    do {
      const ssize_t r = read(stderr_fds[0], &out[i], buf_size);

      if (r > 0) {
        i += r;
      }

      if (out_size - i <= 4096) {
        out_size *= 2;
        out = realloc(out, out_size);
      }

    } while (errno == EAGAIN || errno == EINTR);

    close(stderr_fds[0]);
  }

  int r, status;
  do {
    r = waitpid(pid, &status, 0);
  } while (r == -1 && errno == EINTR);

  out[i] = 0;

  return out;
}

int main() {
  char* argv[3];
  argv[0] = "ls";
  argv[1] = "-la";
  argv[2] = NULL;
  char* out = qx(argv, 0);
  printf("%s", out);
  free(out);
}

언급URL : https://stackoverflow.com/questions/7292642/grabbing-output-from-exec

반응형