如何使用多个命令运行NSTask



我正试图让一个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);
                                                  }];
}

任务在与代码分离的进程中运行,即异步运行。当你在两行之后到达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发送该通知时运行。

以下代码适用于我。

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

大约8年后,我认为grep二进制文件不在/usr/bin中,对我来说它在/bin中。此外,对于awk命令,您将启动路径设置为grep。

最新更新