자기가 만든 프로그램 linux util(pipe, 리다이렉션 )과 같이 쓰
글쓴이: nayana / 작성시간: 수, 2004/11/10 - 10:45오전
아래소스는 tail의 간단한 예제소스입니다.
1 #include "tail.h" 2 3 int main(int argc, char **argv) 4 { 5 TAIL *tf; 6 char *buf; 7 int n; 8 9 if ((tf = opentail(argv[1])) == NULL) 10 { 11 perror("error "); 12 exit(0); 13 } 14 buf = (char *)malloc(256); 15 while(1) 16 { 17 n = readtail(tf, buf, 255, 1); 18 printf("-> %d %s", n, buf); 19 } 20 closetail(tf); 21 free(buf); 22 23 return 0; 24 } 25
1 #include <sys/types.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/time.h> 5 #include <unistd.h> 6 #include <stdio.h> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 #include <errno.h> 10 11 /* 12 * tail 관리를 위한 객체 13 */ 14 typedef struct _TAIL 15 { 16 FILE *fp; // 파일 스트림 17 char filename[256]; // 오픈한 파일 이름 18 int fd; // 파일 스트림에 대한 파일 지정자 19 int revsize; // 최근에 읽었던 파일 크기 20 } TAIL; 21 22 /* 23 * tail을 적용할 파일을 연다. 24 */ 25 TAIL *opentail(char *fname) 26 { 27 TAIL *MTAIL; 28 struct stat fbuf; 29 MTAIL = (TAIL *)malloc(sizeof(TAIL)); 30 if ((MTAIL->fp = fopen(fname, "r")) == NULL) 31 { 32 return NULL; 33 } 34 35 if (stat(fname, &fbuf) < 0) 36 { 37 return NULL; 38 } 39 40 strncpy(MTAIL->filename, fname, 255); 41 42 // 열린 파일 스트림의 파일지정자를 얻어온다. 43 MTAIL->fd = fileno(MTAIL->fp); 44 MTAIL->revsize = fbuf.st_size; 45 return MTAIL; 46 } 47 48 /* 49 * sec시간 간격으로 파일에 추가된 내용을 읽어온다. 50 * 만약 지금의 파일크기가 이전 파일크기 보다 작다면 51 * 파일이 truncate() 되었다고 가정하고 첫라인 부터 52 * 다시 읽어 들인다. 53 */ 54 int readtail(TAIL *LTAIL, char *buf, size_t size, int sec) 55 { 56 fd_set rfds; 57 struct timeval tv; 58 int retval; 59 char *ret; 60 struct stat fbuf; 61 62 while(1) 63 { 64 FD_ZERO(&rfds); 65 FD_SET(LTAIL->fd, &rfds); 66 tv.tv_sec = sec; 67 tv.tv_usec = 0; 68 retval = select(LTAIL->fd+1, &rfds, NULL, NULL, &tv); 69 if (retval) 70 { 71 ret = fgets(buf, size, LTAIL->fp); 72 if (stat(LTAIL->filename, &fbuf) < 0) 73 { 74 return -1; 75 } 76 if (ret == NULL) 77 { 78 // 현재 파일크기가 이전 파일 크기 보다 79 // 작다면 rewind()시킨다. 80 if (fbuf.st_size < LTAIL->revsize) 81 { 82 rewind(LTAIL->fp); 83 } 84 LTAIL->revsize = fbuf.st_size; 85 sleep(sec); 86 continue; 87 } 88 LTAIL->revsize = fbuf.st_size; 89 return 1; 90 } 91 else 92 { 93 return -1; 94 } 95 } 96 return 1; 97 } 98 99 void closetail(TAIL *LTAIL) 100 { 101 fclose(LTAIL->fp); 102 free(LTAIL); 103 }
이프로그램을 실행시키고 예를 들면 b tail.h > log.txt 혹은 b tail.h | more
실행 시키면 리다이렉션이나 파이프 명령어가 먹히질 않습니다.
하지만 내부 명령어를 사용하면 다음과 같이 tail tail.h > log.txt하면 잘됩니다. 파이프나 리다이렉션 기능과도 호환이 잘되도록 하고 싶은데....
어떻게 하면 되나여 그리고 신기한것은 위의 소스를 약간 수정해서
15 while( i != 8) 16 { 17 n = readtail(tf, buf, 255, 1); 18 printf("-> %d %s", n, buf); 19 ++i; 20 }
다음과 같이 하여
b tail.h > log.txt 하면 리다이렉션 잘된다는것입니다.
개인적으로 제가 판단할때는 위의소스는 loop때문에 리다이렉션, 파이프가 먹히질 않는것 같습니다. 하지만 tail 명령어 또한 loop돌면서체크하는것인데 파이프나 리다이렉션이 잘먹습니다. 파이프나 리다이렉션 명령어를 조합해서 쓰려면 어떻게 해야하나요?
Forums:
여러가지 방법이 있습니다.
문제는 스트림간의 파이프 연결 혹은 리디렉션은 일정단위의 버퍼가 차거나 강제로 비울때마다 발생하는 동작이라는것입니다. 특히나 버퍼크기가 1K,2K 정도의 다른 유닉스와는 달리 x86에서의 리눅스는 4K나 된다는 점때문에 버퍼플러싱이 더 중요합니다.
방법1. tail.c에서 setlinebuf(stdout)등으로 라인플러싱으로 전환
방법2. tail.c에서의 printf(...)이후에 fflush(stdout)등으로 강제버퍼플러싱
잘못된 답이 아니길 바랄뿐입니다. :-)
homeless
아직 해보진 않았지만...답변이 달아 있어서 얼마나 마음이 놓이는지 모릅
아직 해보진 않았지만...답변이 달아 있어서 얼마나 마음이 놓이는지 모릅니다.
답변이 없으면 그런기능을 짜야하는데...^^;
일단 해보고 글을 남기겠습니다.
일단 감사합니다.님의 말씀대로 하니까..잘됩니다.오늘도 하나의 팁
일단 감사합니다.
님의 말씀대로 하니까..잘됩니다.
오늘도 하나의 팁(?)을 알게 되었습니다.
댓글 달기