<출처 : 조인시 위키 http://www.joinc.co.kr/modules/moniwiki/wiki.php/Code/C/tail>
tail구현 함수 입니다. 파일에 추가 되는 내용이 있는지 검사해서 줄단위로 읽어들입니다. 로그파일처리를 위한 프로그램등에 유용하게 사용할 수 있을 겁니다. 현재 저는 Apache의 웹로그를 분석해서 PV, Hits를 통계내는 곳에 사용하고 있습니다. 시간단위로 누적 count 값을 RRD에 저장해 둔다면, 변화량을 측정할 수 있게됩니다.
- 파일의 끝에 도달하면 select의 의미가 없으므로 굳이 select를 사용할 필요는 없을 거라고 생각된다. 실제 select부분을 주석처리해도 제대로 작동한다.
사용방법
TAIL *opentail(char *fname); int readtail(TAIL *LTAIL, char *buf, size_t size, int sec); void closetail(TAIL *LTAIL);
- opentail은 tail을 적용할 파일을 열기 위해서 사용한다. 실패하면 NULL을 리턴하고 성공하면 TAIL 객체(구조체 포인터)를 리턴한다.
- readtail은 TAIL 객체를 이용해서 파일로 부터 추가된 내용을 줄단위로 읽어 온다. 줄이 추가되면 size만큼 읽어서 buf에 복사한다. 추가된 줄이 없을 경우 sec만큼 기다린다.
- 입력된 줄을 읽어 왔다면 1을 리턴하고 어떤 이유로 실패 했을 경우 -1을 리턴한다.
#include "tail.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdlib.h> #include <vector> using namespace std; int main(int argc, char **argv) { vector<TAIL *> tflist; TAIL *tf; char *buf; int n, i; // 2개 이상의 파일에 대해서 tail 가능하다. for(i = 1; i < argc; i++) { if((tf = opentail(argv[i])) == NULL) { perror("error "); exit(1); } tflist.push_back(tf); } buf = (char *)malloc(1024); int issleep = 0; while(1) { issleep = 0; for(i = 0; i < tflist.size(); i++) { n = readtail(tflist[i], buf, 1023, 1); if(n > 0) printf("%d : %s", i, buf); issleep |= n; } if (issleep == 0) { sleep(1); printf("Sleep\n"); continue; } } //closetail(tf); free(buf); }
코드
#include <sys/types.h> #include <sys/time.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> /* * tail 관리를 위한 객체 */ typedef struct _TAIL { FILE *fp; // 파일 스트림 char filename[256]; // 오픈한 파일 이름 int fd; // 파일 스트림에 대한 파일 지정자 int revsize; // 최근에 읽었던 파일 크기 } TAIL; /* * tail을 적용할 파일을 연다. */ TAIL *opentail(char *fname) { TAIL *MTAIL; struct stat fbuf; MTAIL = (TAIL *)malloc(sizeof(TAIL)); if ((MTAIL->fp = fopen(fname, "r")) == NULL) { return NULL; } if (stat(fname, &fbuf) < 0) { return NULL; } strncpy(MTAIL->filename, fname, 255); // 열린 파일 스트림의 파일지정자를 얻어온다. MTAIL->fd = fileno(MTAIL->fp); MTAIL->revsize = fbuf.st_size; return MTAIL; } /* * sec시간 간격으로 파일에 추가된 내용을 읽어온다. * 만약 지금의 파일크기가 이전 파일크기 보다 작다면 * 파일이 truncate() 되었다고 가정하고 첫라인 부터 * 다시 읽어 들인다. */ int readtail(TAIL *LTAIL, char *buf, size_t size, int sec) { fd_set rfds; struct timeval tv; int n, retval; char *ret; int fd; struct stat fbuf; FD_ZERO(&rfds); FD_SET(LTAIL->fd, &rfds); tv.tv_sec = sec; tv.tv_usec = 0; retval = select(LTAIL->fd+1, &rfds, NULL, NULL, &tv); if (retval) { ret = fgets(buf, size, LTAIL->fp); if (stat(LTAIL->filename, &fbuf) < 0) { return -1; } if (ret == NULL) { // 현재 파일크기가 이전 파일 크기 보다 // 작다면 rewind()시킨다. if (fbuf.st_size < LTAIL->revsize) { rewind(LTAIL->fp); } LTAIL->revsize = fbuf.st_size; return 0; } LTAIL->revsize = fbuf.st_size; return 1; } else { return -1; } return 1; } void closetail(TAIL *LTAIL) { fclose(LTAIL->fp); free(LTAIL); }
<출처 : 조인시 위키 http://www.joinc.co.kr/modules/moniwiki/wiki.php/Code/C/tail>
'Programming' 카테고리의 다른 글
컴퓨터의 모든 IP 주소 가져오기 (0) | 2009.06.12 |
---|---|
Windows Console 에서 rm -rf 구현 (0) | 2009.06.11 |
쓰레드 동기화 방법론 (0) | 2009.04.30 |
현재 IP Address 값 구하기 (0) | 2009.04.27 |
Windows 폴더, 파일 수 제한 (0) | 2009.04.27 |