获取ObjC中shell命令的输出

pb3s4cty  于 2023-02-05  发布在  Shell
关注(0)|答案(2)|浏览(188)

我读过使用NSTask实现此目的的解决方案:它们看起来都非常非常长......所以我设法使用下面的代码做了完全相同的事情(它同时获得标准输出和标准错误):

NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:@[ @"-c", @"aCommand"]];
NSString *stringToRemove = [task description];
[task launch];
NSString *output = [[task description] stringByReplacingOccurrencesOfString:stringToRemove withString:@""];

使用这种解决方案有什么缺点吗?有没有更短的方法来过滤输出?

qlvxas9a

qlvxas9a1#

使用这种解决方案有什么缺点吗?有没有更短的方法来过滤输出?
是的,有很多缺点。您依赖于description将神奇地返回任务的命令行和输出的实现细节。文档中没有声明这一点,description在调试/日志记录之外的使用也是不可接受的。
也就是说,代码只是为了方便而工作。
但是这段代码实际上并不起作用,如果你要运行的命令从来没有退出,或者需要一段时间才能运行,或者产生了大量的输出,那么这段代码很可能根本没有捕获到任何输出,或者输出被截断了。
使用NSTask的示例往往有点长,这是有原因的,因为管理进程之间的I/O实际上相当困难,需要考虑许多不同的选项。

yrefmtwq

yrefmtwq2#

如果您的目标只是运行命令并等待其退出(例如,从CLI应用程序中的shell命令获取信息),则可以使用以下命令(启用ARC):

// Start the task with path and arguments.
    NSTask* task = [NSTask new];
    [task setExecutableURL:[NSURL fileURLWithPath:@"/path/to/task"]];
    [task setArguments:@[@"your", @"arguments", @"here"]];

    // Intercept the standard output of the process.
    NSPipe* output = [NSPipe pipe];
    [task setStandardOutput:output];

    // Launch and wait until finished.
    [task launch];
    [task waitUntilExit];

    // Read all data from standard output as NSData.
    NSData* resultData = [[output fileHandleForReading] readDataToEndOfFile];
    
    // Convert NSData to string (could be combined with above when ARC used).
    NSString* result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];

这在长度上看起来并不是不合理的(而且可能会缩短,尽管我为了可读性而保留了它),如果您经常使用它,您可以将其抽象为一个函数。
我还注意到,由于您没有在代码中重定向输出,它还会将输出打印到控制台,这可能是无意的。

相关问题