1

我需要运行一个 .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 仅用于检查输出。现在我的代码冻结了,甚至没有进入警报面板。

4

3 回答 3

3

请参阅此问题的答案。

您的脚本中应该修复几件事:

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

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

#!/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]];
...
于 2010-08-20T08:29:24.277 回答
1

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

/*
// 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]];
        }
}
于 2010-08-21T21:03:19.370 回答
0

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

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

您必须放弃 while 循环并在 NSFileHandle 上使用“readInBackgroundAndNotify”模式来获得非阻塞 I/O 标准输出流行为!

请参阅:NSTask/NSPipe STDIN 挂在大数据上,有时...

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

于 2010-08-22T07:16:49.297 回答