如何使用NSTask运行.sh文件并获取其输出?

我需要运行.sh文件并获取其输出。 我还需要查看文件的设置。

.sh文件只是通过终端运行java应用程序。

有任何想法吗? 我真的被这个……

以利亚

server.sh文件:

echo Starting Jarvis Program D. ALICE_HOME=. SERVLET_LIB=lib/servlet.jar ALICE_LIB=lib/aliceserver.jar JS_LIB=lib/js.jar # Set SQL_LIB to the location of your database driver. SQL_LIB=lib/mysql_comp.jar # These are for Jetty; you will want to change these if you are using a different http server. HTTP_SERVER_LIBS=lib/org.mortbay.jetty.jar PROGRAMD_CLASSPATH=$SERVLET_LIB:$ALICE_LIB:$JS_LIB:$SQL_LIB:$HTTP_SERVER_LIBS java -classpath $PROGRAMD_CLASSPATH -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1 

我目前的代码:

 NSTask *server = [NSTask new]; [server setLaunchPath:@"/bin/sh"]; [server setArguments:[NSArray arrayWithObject:@"/applications/jarvis/brain/server.sh"]]; NSPipe *outputPipe = [NSPipe pipe]; [server setStandardInput:[NSPipe pipe]]; [server setStandardOutput:outputPipe]; [server launch]; NSMutableString *outputString = [NSMutableString string]; while ([outputString rangeOfString:@"Jarvis>"].location == NSNotFound) { [outputString appendString:[[[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding] autorelease]]; NSRunAlertPanel(@"", outputString, @"", @"", @""); } 

NSRunAlertPanel仅用于检查输出。 现在我的代码冻结了,甚至没有进入alertpanel。

请参阅此问题的答案。

您的脚本中应该修复一些问题:

  • 脚本应该以shebang开头。 还要确保脚本的可执行位已设置。
  • 由于环境变量是相对于shell脚本目录设置的,因此需要确保脚本目录是当前目录。
  • 您需要导出应该对Java进程可见的环境变量。
  • 在最后一行中,您可以使用exec将shell进程替换为运行Jetty的Java可执行文件。

这是您的脚本的修订版本:

 #!/bin/sh echo Starting Jarvis Program D. cd "`dirname \"$0\"`" export ALICE_HOME=. export SERVLET_LIB=lib/servlet.jar export ALICE_LIB=lib/aliceserver.jar export JS_LIB=lib/js.jar # Set SQL_LIB to the location of your database driver. export SQL_LIB=lib/mysql_comp.jar # These are for Jetty; you will want to change these if you are using a different http server. export HTTP_SERVER_LIBS=lib/org.mortbay.jetty.jar export PROGRAMD_CLASSPATH=$SERVLET_LIB:$ALICE_LIB:$JS_LIB:$SQL_LIB:$HTTP_SERVER_LIBS exec java -classpath $PROGRAMD_CLASSPATH -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1 

使用多个参数调用Objective-C中的shell脚本:

 NSTask *server = [NSTask new]; [server setLaunchPath:@"/bin/sh"]; [server setArguments:[NSArray arrayWithObjects:@"/applications/jarvis/brain/server.sh", @"argument", nil]]; ... 

使用AMShellWrapperTest.app,您可以通过修改BannerController.m中的“ – (void)appendOutput:(NSString *)output”来过滤(保存,…)server.sh的stdout流。 (…但也许有更好的方法来做到这一点…)

 /* // output from stdout - modified AMShellWrapper/AMShellWrapperTest/BannerController.m (http://www.harmless.de/cocoa-code.php) to print server.sh setup information to "Error Messages:" text output field (or Console.app as an alternative) and the Q & A dialog to the "Output:" text field - use of default charliebot, http://sourceforge.net/projects/charliebot/, modified only to run server.sh with complete path (here: ~/Desktop/charliebot/server.sh) in AMShellWrapperTest.app */ - (void)appendOutput:(NSString *)output { NSMutableString *outputString = [NSMutableString string]; if ( ([output rangeOfString:@"Charlie>"].location != NSNotFound ) || \ ([output rangeOfString:@"[Charlie] user>"].location != NSNotFound ) ) { [self write: output]; [self write: @"\n"]; } else { [outputString appendString: output]; //[outputString writeToFile:@"/dev/console" atomically: NO]; // alternative [errorOutlet setString:[[errorOutlet string] stringByAppendingString: outputString]]; } } 

是的,但为什么我的代码(上面发布的)不起作用?

我想你的“Jarvis>”行是server.sh输出流的第一行,它需要一些用户输入,这意味着这行不完整而没有终止换行符“\ n”。 如果在Terminal.app中运行了server.sh,则用户必须按返回键才能继续对话。 while循环的条件代码(NSNotFound)无法在这个不完整的行上完成它的工作(这将中止while循环)并被卡住。

你必须删除while循环并在NSFileHandle上使用’readInBackgroundAndNotify’模式来获得非阻塞的I / O标准输出流行为!

请参阅: NSTask / NSPipe STDIN挂起大数据,有时……

因此,如果您愿意,只需删除GUI代码,即可将AMShellWrapperTest.app的源代码转换为纯命令行工具。