2012-02-22 72 views
4

我試圖做一個NSTask運行如下命令:如何使用多個命令運行NSTask

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

但結果只是

結果:

我在做什麼錯?

編輯

- (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 2016-12-16 12:58:23

回答

5

在一個單獨的進程從您的代碼運行,即異步地任務。他們可能還沒有完成(他們甚至可能還沒有發起!)在你到達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 2012-02-22 18:36:38

+0

你知道,我只是想過一個更好的方法來做到這一點。請參閱我的編輯。 – 2012-02-22 18:50:09

+0

請參閱我的編輯。我已經添加了代碼,但是我仍然返回一個空字符串。 – dhrm 2012-02-22 19:05:23

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