Как запустить файл .sh с помощью NSTask и получить его вывод - PullRequest
1 голос
/ 20 августа 2010

Мне нужно запустить файл .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 просто для проверки вывода.Теперь мой код зависает и даже не попадает на панель предупреждений.

Ответы [ 3 ]

2 голосов
/ 20 августа 2010

См. Ответ на этот вопрос .

В вашем скрипте необходимо исправить несколько вещей:

  • Скрипт должен начинаться спритон.Также убедитесь, что в сценарии установлен исполняемый бит.
  • Поскольку переменные среды установлены относительно каталога сценария оболочки, необходимо убедиться, что каталог сценария является текущим каталогом.
  • Вам необходимо экспортировать переменные среды, которые должны быть видны процессу Java.
  • В последней строке вы можете использовать exec для замены процесса оболочки на исполняемый файл Java, выполняющий Jetty.

Вот пересмотренная версия вашего скрипта:

#!/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 с несколькими аргументами:

NSTask *server = [NSTask new];
[server setLaunchPath:@"/bin/sh"];
[server setArguments:[NSArray arrayWithObjects:@"/applications/jarvis/brain/server.sh", @"argument", nil]];
...
1 голос
/ 22 августа 2010

Используя AMShellWrapperTest.app, вы можете фильтровать (сохранять, ...) поток stdout файла server.sh, изменяя вывод «- (void) appendOutput: (NSString *)» в BannerController.m.(... но, может быть, есть лучший способ сделать это ...)

/*
// 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]];
        }
}
0 голосов
/ 22 августа 2010

да, но почему мой код (опубликованный выше) не работает?

Я полагаю, ваша строка "Jarvis>" является первой строкой выходного потока server.shэто ожидает некоторого пользовательского ввода, что означает, что эта строка является неполной без завершающего символа новой строки "\ n".Если server.sh был запущен в Terminal.app, пользователь должен будет нажать клавишу возврата, чтобы продолжить диалог.Условный код цикла while (NSNotFound) не может завершить свою работу на этой неполной строке (которая должна была бы прервать цикл while) и застревает.

Вы должны отбросить цикл while и использовать readInBackgroundAndNotify'режим в NSFileHandle для получения неблокирующего поведения потока ввода-вывода!

См .: NSTask / NSPipe STDIN зависает на больших данных, иногда ...

Итак, если хотите, просто преобразуйте исходный код AMShellWrapperTest.app в чистый инструмент командной строки, удалив код GUI.

...