Domanda

Ho bisogno di leggere l'ultima riga aggiunta ad un file di log , in tempo reale, e la cattura quella linea viene aggiunto.

Qualcosa di simile a tail -f.

Quindi il mio primo tentativo è stato quello di usare tail -f utilizzando NSTask.

Non riesco a vedere alcun output utilizzando il codice qui sotto:

    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);

posso vedere l'output come previsto quando si utilizza:

[server setLaunchPath:@"/bin/ls"];
  1. Come posso catturare l'output di quella coda NSTask?

  2. C'è qualche alternativa a questo metodo, dove posso aprire un flusso di file e ogni volta che si aggiunge una linea, uscita sullo schermo? (Funzionalità di registrazione di base)

È stato utile?

Soluzione

Questo è un po 'difficile da fare la tua strada, come readDataToEndOfFile attenderà fino a quando tail chiude il flusso di output prima di tornare, ma tail -f non chiude mai il flusso di output (stdout). Tuttavia, questo è in realtà piuttosto semplice da fare con la base C di I / O di codice, così ho montata su una semplice classe FileTailer che si possono verificare. Non è niente di eccezionale, ma dovrebbe mostrare come si fa. Here're le fonti per FileTailer.h , FileTailer.m , e un collaudatore .

La carne della classe è abbastanza semplice. Si passa un blocco, e si legge un carattere dal flusso (se possibile) e lo passa al blocco; se EOF è stato raggiunto, si aspetta un certo numero di secondi (determinato da refresh) e poi cerca di leggere nuovamente il flusso.

- (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];
        }
    }
}

Si può chiamare abbastanza semplicemente, in questo modo:

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

(Caveat: ho scritto la classe FileTailer piuttosto veloce, quindi è una specie di brutto momento e deve essere ripulito un po ', ma dovrebbe servire da esempio decente su come leggere un file a tempo indeterminato, à la tail -f.)

Altri suggerimenti

Ecco un modo di usare "file di log tail -f" via NSTask in Objective-C:

  

asynctask.m - codice di esempio che mostra come implementare stdin, stdout flussi e stderr asincroni per l'elaborazione dei dati con NSTask

     

...

     

Essendo un'applicazione GUI-less (vale a dire uno strumento a riga di comando Fondazione-based), asynctask.m gestisce un NSRunLoop manualmente   per consentire l'utilizzo di asincroni notifiche "waitForDataInBackgroundAndNotify". Inoltre, asynctask.m   Usi pthread_create (3) e pthread_detach (3) per la scrittura di più di 64 KB alla stdin di un NSTask.

Il codice sorgente di asynctask.m disponibile all'indirizzo: http://www.cocoadev.com/index .pl? NSPipe

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top