2012-02-22 2 views
4

Я пытаюсь сделать NSTask запустить команду:Как запустить NSTask с несколькими командами

пс -clx | grep 'Finder' | AWK '{печать $ 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); 
} 

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

Результат:

Что я делаю неправильно?

EDIT

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

Не имеет смысла запускать задачи после того, как вы привязали наблюдателя? Что делать, если задача завершается до присоединения наблюдателя? – eonist

ответ

5

Задачи выполняются в отдельном процессе из кода, т.е. asychronously. Вероятно, они не закончили (возможно, они даже не запустились!) К моменту, когда вы дойдете до 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: Observing Process Lifetime Without Polling. Каждый NSTask отправит NSTaskDidTerminateNotification, когда он прекратится (вы должны, в идеале, проверить его код возврата, а не предполагать его успешное выполнение). Вы можете создать блок, который будет запущен, когда task3 отправит это уведомление.

+0

Не могли бы вы предоставить мне небольшой пример, показывающий, как я могу это сделать с помощью GCD? – dhrm

+0

Знаешь, я просто подумал о том, как это сделать. См. Мое редактирование. –

+0

См. Мое редактирование. Я добавил код, но я все еще возвращаю пустую строку. – dhrm

2

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

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); 
Смежные вопросы