views:

168

answers:

3

I need to run an .sh file and get its output. I need to see the setup of the file as well.

The .sh file simply runs a java app through terminal.

Any ideas? I'm truly stuck on this.....

Elijah

The server.sh file:

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

My current code:

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, @"", @"", @"");

}

The NSRunAlertPanel is just for checking the output. Now my code is freezing and not even getting to the alertpanel.

+2  A: 

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]];
...
sakra
Yes. Did all of that and it's returning the echo at the beginning on the .sh file, but not the setup or the final program. There is a user input field as well.
Elijah W.
Can you post an outline of your shell script?
sakra
yes. I put it in my question.
Elijah W.
I don't think that NSTask will let me view the setup for the .sh file, as terminal does.
Elijah W.
ok thanks! would I then replace "dirname" with the path to the directory: /applications/jarvis/brain ?
Elijah W.
no. you can use dirname literally. It is a shell command.
sakra
ok... it looks like it's freezing my code..... I'm posting it up in the question.
Elijah W.
Tried it in the AMShellWrapperTest and it's printing out EVERYTHING!! So it's just my code that's causing problems
Elijah W.
any ideas? -----
Elijah W.
Your shell script seems to require an additional argument, which is then passed to the java executable as $1. The NSTask code launches your script without arguments.
sakra
Can you show an example of this?
Elijah W.
See updated answer.
sakra
Ok I copied your code snippet and now, it's printing out the ECHO!!!! 1 step closer....but that seems like the only thing it's printing. That's completely weird because it printed out everything in the AMShellWrapper. Any ideas?
Elijah W.
I'm reading the error pipe and it's getting this error: Could not find "argument"! - so obviously, argument doesn't go there, what should?
Elijah W.
Sorry I have no idea what argument should go there. "argument" was just meant to be a place holder. After all, it's your script, so you should know.
sakra
Ok....me neither....I'm very new to java. How would I find out?
Elijah W.
+1  A: 

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]];
        }
}
notmp
yes, but why isn't my code (posted above) not working?
Elijah W.
A: 

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.

tilo
yes, that's true, but why is it not printing anything except the echo? I need to add an argument, but I'm not sure what argument.
Elijah W.