반응형
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
반응형
'programing' 카테고리의 다른 글
SQL(Oracle)의 느낌표 (0) | 2023.11.07 |
---|---|
오라클에서 예약된 작업을 삭제하는 방법 (0) | 2023.11.07 |
PL/SQL <>의 의미는 무엇입니까? (0) | 2023.11.07 |
오라클 프로시저 내에서 date parameter를 전달하는 방법은? (0) | 2023.11.07 |
원래 변수는 그대로 유지하면서 mutate_at로 새 변수 만들기 (0) | 2023.11.07 |