자기가 만든 프로그램 linux util(pipe, 리다이렉션 )과 같이 쓰

nayana의 이미지

아래소스는 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돌면서체크하는것인데 파이프나 리다이렉션이 잘먹습니다. 파이프나 리다이렉션 명령어를 조합해서 쓰려면 어떻게 해야하나요?
kihlle의 이미지

문제는 스트림간의 파이프 연결 혹은 리디렉션은 일정단위의 버퍼가 차거나 강제로 비울때마다 발생하는 동작이라는것입니다. 특히나 버퍼크기가 1K,2K 정도의 다른 유닉스와는 달리 x86에서의 리눅스는 4K나 된다는 점때문에 버퍼플러싱이 더 중요합니다.

방법1. tail.c에서 setlinebuf(stdout)등으로 라인플러싱으로 전환
방법2. tail.c에서의 printf(...)이후에 fflush(stdout)등으로 강제버퍼플러싱

잘못된 답이 아니길 바랄뿐입니다. :-)

homeless

nayana의 이미지

아직 해보진 않았지만...답변이 달아 있어서 얼마나 마음이 놓이는지 모릅니다.
답변이 없으면 그런기능을 짜야하는데...^^;
일단 해보고 글을 남기겠습니다.

nayana의 이미지

일단 감사합니다.
님의 말씀대로 하니까..잘됩니다.
오늘도 하나의 팁(?)을 알게 되었습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.