자기가 만든 프로그램 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
아직 해보진 않았지만...답변이 달아 있어서 얼마나 마음이 놓이는지 모릅
아직 해보진 않았지만...답변이 달아 있어서 얼마나 마음이 놓이는지 모릅니다.
답변이 없으면 그런기능을 짜야하는데...^^;
일단 해보고 글을 남기겠습니다.
일단 감사합니다.님의 말씀대로 하니까..잘됩니다.오늘도 하나의 팁
일단 감사합니다.
님의 말씀대로 하니까..잘됩니다.
오늘도 하나의 팁(?)을 알게 되었습니다.
댓글 달기