2011-01-12 2 views
3

로그 파일에 마지막으로 추가 된 행을 실시간으로 읽고 추가 할 행을 캡처해야합니다.NSTask를 사용하여 Tail -f와 비슷한 것을 얻는 방법

테일 -f와 비슷한 것.

그래서 첫 번째 시도는 NSTask를 사용하여 Tail -f를 사용하는 것이 었습니다. 사용할 때 예상대로 출력을 볼 수 있습니다

NSTask *server = [[NSTask alloc] init]; 
    [server setLaunchPath:@"/usr/bin/tail"]; 
    [server setArguments:[NSArray arrayWithObjects:@"-f", @"/path/to/my/LogFile.txt",nil]]; 

    NSPipe *outputPipe = [NSPipe pipe]; 
    [server setStandardInput:[NSPipe pipe]]; 
    [server setStandardOutput:outputPipe]; 

    [server launch]; 
    [server waitUntilExit]; 
    [server release]; 

    NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile]; 
    NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; 
    NSLog (@"Output \n%@", outputString); 

:

나는 아래의 코드를 사용하여 출력을 볼 수 없습니다

[server setLaunchPath:@"/bin/ls"]; 
  1. 를 내가의 출력을 캡처 할 수있는 방법 그 꼬리 NSTask?

  2. 파일로 스트림을 열고 라인을 추가 할 때마다 화면에 출력 할 수있는 방법이 있습니까? (기본 로깅 기능)

답변

4

tail가 돌아 오기 전에 출력 스트림을 닫지 만 tail -f 결코 출력 스트림 (표준 출력)을 종료되지 않습니다 때까지 readDataToEndOfFile가 대기로이, 당신의 방법을 조금 까다 롭습니다. 그러나 이것은 실제로 기본 C I/O 코드로 수행하는 것이 매우 간단하므로 체크 아웃 할 수있는 간단한 FileTailer 클래스를 작성했습니다. 멋진 것은 아니지만 어떻게 완료되었는지 보여줄 것입니다. 여기에 FileTailer.h, FileTailer.mtest driver의 출처가 있습니다.

클래스의 고기는 매우 간단합니다. 블록을 전달하고 가능한 경우 스트림에서 문자를 읽고이를 블록으로 전달합니다. EOF에 도달하면 수 초 (refresh으로 결정됨)를 기다린 다음 스트림을 다시 읽으려고 시도합니다. 나는 FileTailer 클래스는 꽤 ​​빨리 썼다, 그래서 지금 가지 추한 및 비트를 청소해야합니다 :

FileTailer *tail = [[[FileTailer alloc] initWithStream:stdin refreshPeriod:3.0] autorelease]; 
[tail readIndefinitely:^ void (int ch) { printf("%c", ch); }]; 

(경고 :

- (void)readIndefinitely:(void (^)(int ch))action 
{ 
    long pos = 0L; 
    int ch = 0; 

    while (1) { 
     fseek(in, pos, SEEK_SET); 
     int ch = fgetc(in); 
     pos = ftell(in); 
     if (ch != EOF) { 
      action(ch); 
     } else { 
      [NSThread sleepForTimeInterval:refresh]; 
     } 
    } 
} 

이 같은, 아주 간단하게 호출 할 수 있습니다 하지만 라 tail -f A, 무기한 파일을 읽는 방법에 알맞은 예로서 봉사해야한다)

+0

은 루프를 통과 할 때마다에'fseek' 호출 할 필요가 있습니까? 'fgetc'가'EOF'를 리턴 한 후에도 호출 할 필요가 있습니까? – benzado

+0

위대한 작품, 난 그냥 다른 스레드에서 주요 하나를 차단하지 않아야했다. 솔루션을 작성하기 위해 시간을 가져 주셔서 감사합니다. 정말 감사! – Bach

+0

@benzado : 엄밀히 말하면, 아니오. 쓰레드가 잠들기 직전에'ftell' 호출을 움직일 수 있고, 깨어 난 후에'fseek' 만 호출 할 수 있습니다; 이 코드는 약간 단순화되었습니다. – mipadi

1

여기 오브젝티브 C에 NSTask를 통해 "꼬리 -f 로그 파일"을 사용하는 방법은 다음과 같습니다.

asynctask.m - 비동기 표준 입력, NSTask

와 데이터를 처리하기위한 표준 출력 & 열려진 스트림을 구현하는 방법을 보여준다 샘플 코드 ...

GUI가없는 애플리케이션 인 (즉, Foundation 기반 명령 줄 도구 인 asynctask.m은 NSRunLoop을 수동으로 실행하여 비동기식 "waitForDataInBackgroundAndNotify"알림을 사용하도록 설정합니다. 또한 asynctask.m 은 NSTask의 표준에 64KB를 초과하여 쓰기 위해 pthread_create (3) 및 pthread_detach (3)를 사용합니다.에서 확인할 수 asynctask.m의

소스 코드 : http://www.cocoadev.com/index.pl?NSPipe

관련 문제