Как запустить NSTask с несколькими командами - PullRequest
4 голосов
/ 22 февраля 2012

Я пытаюсь заставить NSTask запустить такую ​​команду:

ps -clx |grep 'Finder' |awk '{print $ 2}'

Вот мой метод

- (void) processByName:(NSString*)name {
    NSTask *task1 = [[NSTask alloc] init];
    NSPipe *pipe1 = [NSPipe pipe];
    [task1 waitUntilExit];
    [task1 setLaunchPath: @"/bin/ps"];
    [task1 setArguments: [NSArray arrayWithObjects: @"-clx", nil]];
    [task1 setStandardOutput: pipe1];

    NSTask *task2 = [[NSTask alloc] init];
    NSPipe *pipe2 = [NSPipe pipe];
    [task2 setLaunchPath: @"/usr/bin/grep"];
    [task2 setArguments: [NSArray arrayWithObjects: @"'Finder'", nil]];
    [task2 setStandardInput:pipe1];
    [task2 setStandardOutput: pipe2];

    NSTask *task3 = [[NSTask alloc] init];
    NSPipe *pipe3 = [NSPipe pipe];
    [task3 setLaunchPath: @"/usr/bin/grep"];
    [task3 setArguments: [NSArray arrayWithObjects: @"'{print $2}'", nil]];
    [task3 setStandardInput:pipe2];
    [task3 setStandardOutput: pipe3];

    NSFileHandle *file = [pipe3 fileHandleForReading];

    [task1 launch];
    [task2 launch];
    [task3 launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    NSString *string;
    string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];

    NSLog(@"Result: %@", string);
}

Но результат просто

Результат:

Что я делаю не так?

РЕДАКТИРОВАТЬ

- (void) processByName:(NSString*)name {
    NSTask *task1 = [[NSTask alloc] init];
    NSPipe *pipe1 = [NSPipe pipe];
    [task1 waitUntilExit];
    [task1 setLaunchPath: @"/bin/ps"];
    [task1 setArguments: [NSArray arrayWithObjects: @"-clx", nil]];
    [task1 setStandardOutput: pipe1];

    NSTask *task2 = [[NSTask alloc] init];
    NSPipe *pipe2 = [NSPipe pipe];
    [task2 setLaunchPath: @"/usr/bin/grep"];
    [task2 setArguments: [NSArray arrayWithObjects: @"'Finder'", nil]];
    [task2 setStandardInput:pipe1];
    [task2 setStandardOutput: pipe2];

    NSTask *task3 = [[NSTask alloc] init];
    NSPipe *pipe3 = [NSPipe pipe];
    [task3 setLaunchPath: @"/usr/bin/grep"];
    [task3 setArguments: [NSArray arrayWithObjects: @"'{print $2}'", nil]];
    [task3 setStandardInput:pipe2];
    [task3 setStandardOutput: pipe3];

    NSFileHandle *file = [pipe3 fileHandleForReading];

    [task1 launch];
    [task2 launch];
    [task3 launch];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSTaskDidTerminateNotification
                                                      object:task3
                                                       queue:nil
                                                  usingBlock:^(NSNotification* notification){

                                                      NSData * data = [file readDataToEndOfFile];

                                                      NSString * string;
                                                      string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
                                                      NSLog(@"Result: %@", string);
                                                  }];
}

Ответы [ 2 ]

5 голосов
/ 22 февраля 2012

Задачи выполняются отдельно от вашего кода, то есть асинхронно. Они, вероятно, еще не закончили (возможно, даже не запустили!) К тому времени, как вы доберетесь до readDataToEndOfFile двумя строками позже.

Если вы уже находитесь в фоновом потоке, вы можете опросить их статус: while( ![task isRunning]){, или, если вы в основном потоке, я бы предложил использовать GCD, чтобы поместить это в очередь и выполнить опрос есть.

На самом деле лучше использовать уведомления:

[task3 launch];

[[NSNotificationCenter defaultCenter] addObserverForName:NSTaskDidTerminateNotification
                                                  object:task3
                                                   queue:nil
                                              usingBlock:^{

    NSData * data = [file readDataToEndOfFile];

    NSString * string;
    string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];

    NSLog(@"Result: %@", string);
}];

См. TN2050: время жизни процесса без опроса . Каждый NSTask будет отправлять NSTaskDidTerminateNotification, когда завершится (в идеале вы должны проверить его код возврата, а не предполагать, что он успешно работал). Вы можете создать блок для запуска, когда task3 отправляет это уведомление.

2 голосов
/ 08 мая 2014

У меня работает следующий код.

NSTask *task1 = [[NSTask alloc] init];
NSPipe *pipe1 = [NSPipe pipe];
[task1 waitUntilExit];
[task1 setLaunchPath: @"/bin/sh"];
[task1 setArguments: [NSArray arrayWithObjects: @"-c",@"ps -A |grep -m1 Finder | awk '{print $1}'", nil]];
[task1 setStandardOutput: pipe1];
[task1 launch];

NSFileHandle *file = [pipe1 fileHandleForReading];
NSData * data = [file readDataToEndOfFile];

NSString * string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(@"Result: %@", string);
...