How would I run an .sh file using NSTask and get its output?

左心房为你撑大大i 提交于 2019-12-08 04:01:25
sakra

See answer to this question.

There are a couple of things that should be fixed in your script:

  • The script should begin with a shebang. Also make sure that the script has its executable bit set.
  • Because the environment variables are set up relative to the shell script directory, you need to make sure that the script directory is the current directory.
  • You need to export the environment variables that should be visible to the Java process.
  • In the last line you can use exec to replace the shell process with the Java executable that runs Jetty.

Here is a revised version of your script:

#!/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

Invoking the shell script in Objective-C with multiple arguments:

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

Using AMShellWrapperTest.app you can filter (save, ...) the stdout stream of server.sh by modifying "- (void)appendOutput:(NSString *)output" in BannerController.m. (... but maybe there is a better way to do this ...)

/*
// 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]];
        }
}

yes, but why isn't my code (posted above) not working?

I guess your "Jarvis>" line is the first line of the server.sh ouput stream that expects some user input, which means that this line is incomplete without a terminating newline character "\n". If server.sh had been run in Terminal.app, the user would have to press the return key to let the dialog continue. The conditional code of the while loop (NSNotFound) cannot finish its job on this incomplete line (which would be to abort the while loop) and gets stuck.

You have to drop the while loop and use the 'readInBackgroundAndNotify' mode on NSFileHandle to get non-blocking I/O stdout stream behaviour!

See: NSTask/NSPipe STDIN hangs on large data, sometimes...

So, if you like, just transform the source code of AMShellWrapperTest.app into a pure command-line tool by removing the GUI code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!