【问题标题】:How to run NSTask with multiple commands如何使用多个命令运行 NSTask
【发布时间】:2012-03-13 02:31:12
【问题描述】:

我正在尝试让 NSTask 运行这样的命令:

ps -clx | grep '查找器' | 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);
                                                  }];
}

【问题讨论】:

  • 附加观察者后启动任务不是更有意义吗?如果一个任务在观察者被附加之前完成怎么办?

标签: objective-c nstask


【解决方案1】:

任务在与您的代码不同的进程中运行,即异步运行。当您在两行后到达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 发送通知时运行的块。

【讨论】:

  • 能否请你提供一个小例子来说明我如何使用 GCD 做到这一点?
  • 你知道,我只是想到了一个更好的方法来做到这一点。请查看我的编辑。
  • 请看我的编辑。我已经添加了代码,但我仍然返回一个空字符串。
  • 您是否验证了您正在运行的命令字符串在您将其输入到 CL 时是否符合您的预期?我看到两件事看起来很有趣:您没有使用方法的参数,并且您正在运行 grep '{print $2}' 作为第三个任务——您的意思是 awk
  • 我无法从代码“编辑”部分得到正确的结果
【解决方案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);

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-26
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 2012-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多