NSTask NSPipe - objective c command line help

后端 未结 2 610
梦毁少年i
梦毁少年i 2020-12-03 02:24

Here is my code:

task = [[NSTask alloc] init];
[task setCurrentDirectoryPath:@\"/applications/jarvis/brain/\"];
[task setLaunchPath:@\"/applications/jarvis/b         


        
相关标签:
2条回答
  • 2020-12-03 02:50

    The solution above is freezing because it's synchronous. Call to [server waitUntilExit] blocks the run loop until the tasks is done.

    Here's the async solution for getting the task output.

    task.standardOutput = [NSPipe pipe];
    [[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) {
        NSData *data = [file availableData]; // this will read to EOF, so call only once
        NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    
        // if you're collecting the whole output of a task, you may store it on a property
        [self.taskOutput appendData:data];
    }];
    

    Probably you want to repeat the same above for task.standardError.

    IMPORTANT:

    When your task terminates, you have to set readabilityHandler block to nil; otherwise, you'll encounter high CPU usage, as the reading will never stop.

    [task setTerminationHandler:^(NSTask *task) {
    
        // do your stuff on completion
    
        [task.standardOutput fileHandleForReading].readabilityHandler = nil;
        [task.standardError fileHandleForReading].readabilityHandler = nil;
    }];
    

    This is all asynchronous (and you should do it async), so your method should have a ^completion block.

    0 讨论(0)
  • 2020-12-03 02:51

    Xcode Bug
    There's a bug in Xcode that stops it from printing any output after a a new task using standard output is launched (it collects all output, but no longer prints anything). You're going to have to call [task setStandardInput:[NSPipe pipe]] to get it to show output again (or, alternatively, have the task print to stderr instead of stdout).


    Suggestion for final code:

    NSTask *server = [NSTask new];
    [server setLaunchPath:@"/bin/sh"];
    [server setArguments:[NSArray arrayWithObject:@"/path/to/server.sh"]];
    [server setCurrentDirectoryPath:@"/path/to/current/directory/"];
    
    NSPipe *outputPipe = [NSPipe pipe];
    [server setStandardInput:[NSPipe pipe]];
    [server setStandardOutput:outputPipe];
    
    [server launch];
    [server waitUntilExit]; // Alternatively, make it asynchronous.
    [server release];
    
    NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
    NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; // Autorelease optional, depending on usage.
    
    0 讨论(0)
提交回复
热议问题