NSTask NSPipe - 目标C命令行帮助
这里是我的代码:NSTask NSPipe - 目标C命令行帮助
task = [[NSTask alloc] init];
[task setCurrentDirectoryPath:@"/applications/jarvis/brain/"];
[task setLaunchPath:@"/applications/jarvis/brain/server.sh"];
NSPipe * out = [NSPipe pipe];
[task setStandardOutput:out];
[task launch];
[task waitUntilExit];
[task release];
NSFileHandle * read = [out fileHandleForReading];
NSData * dataRead = [read readDataToEndOfFile];
NSString * stringRead = [[[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding] autorelease];
所以我想复制这样的:
cd /applications/jarvis/brain/
./server.sh
但在Objective-C使用NSTask。
由于某些原因,当我运行此代码时,stringRead,不会返回任何内容。它应该返回当我启动.sh文件时终端正在返回的内容。正确?
任何想法?
利亚
Xcode的错误
有一个在Xcode中,从后使用标准输出新任务启动打印任何输出停止一个bug(它收集所有输出,但不再打印任何东西)。你将不得不打电话[task setStandardInput:[NSPipe pipe]]
让它再次显示输出(或者,也可以将任务打印到stderr而不是stdout)。
建议最终的代码:
NSTask *server = [NSTask new];
[server setLaunchPath:@"/bin/sh"];
[server setArguments:[NSArray arrayWithObject:@"/path/to/server.sh"]];
[server setCurrentDirectoryPath:@"/path/to/current/directory/"];
NSPipe *outputPipe = [NSPipe pipe];
[server setStandardInput:[NSPipe pipe]];
[server setStandardOutput:outputPipe];
[server launch];
[server waitUntilExit]; // Alternatively, make it asynchronous.
[server release];
NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; // Autorelease optional, depending on usage.
看起来这似乎也冻结了我的代码......呵呵......其他想法呢? – objectiveccoder001 2010-08-13 04:06:50
而且,我试图在回声“你好世界”它返回空白....日期回复空白。 – objectiveccoder001 2010-08-13 04:09:50
即使使用'[server setStandardInput:[NSPipe pipe]]'?这有点奇怪。你是否逐字复制了我的代码?试试吧,看看它是否可以与只包含'echo“Hello World”的文件一起工作; pwd | ls'。 如果它仍然不起作用,请告诉我们您正在使用的Xcode的版本,并查看是否将字符串写入文件会生成任何输出(可能只是Xcode终端不打印更多输出)。 – 2010-08-13 08:15:21
将溶液上方冻结,因为它是同步的。 致电[server waitUntilExit]
会阻止运行循环,直到完成任务。
以下是获取任务输出的异步解决方案。
task.standardOutput = [NSPipe pipe];
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) {
NSData *data = [file availableData]; // this will read to EOF, so call only once
NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// if you're collecting the whole output of a task, you may store it on a property
[self.taskOutput appendData:data];
}];
也许你想重复一遍上面的task.standardError
。
重要:
当任务结束,你必须设置readabilityHandler块零;否则,你会遇到高CPU使用率,因为阅读永远不会停止。
[task setTerminationHandler:^(NSTask *task) {
// do your stuff on completion
[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
}];
这是所有异步(你应该这样做async),所以你的方法应该有一个^完成块。
完美。正在寻找一个块API的例子。 – uchuugaka 2015-05-23 07:47:07
你确定server.sh脚本输出标准输出吗?也许你应该把stderr连接起来,看看它是否包含任何东西。 您可能还想考虑在任务运行时从管道读取数据,因为如果在您未读取时尝试向管道打印过多且缓冲区填满,则下次任务将挂起它会尝试输出任何东西。 – 2010-08-09 21:07:34
我不确定。你能告诉我一个例子吗?是的,我删除了[任务发布]和[任务waitUntilExit]。同样的问题。 – objectiveccoder001 2010-08-09 21:23:54
你是否以编程方式(或在gdb中)检查stringRead的内容,还是试图使用NSLog或其他东西打印出来?如果您使用的是NSLog并且根本看不到输出,请检查您的输出的“应用程序”>“实用程序”中的控制台日志。 Shell脚本作为NSTask运行,可以使Xcode控制台输出停止工作。 除此之外,我第二凯文的意见,以检查是否有标准错误的东西(只需添加第二个管道,并将其设置为您的任务的标准错误),并且不依赖于管道能够缓冲所有你的任务的输出。 – puzzle 2010-08-09 21:39:40