Получить стандартный вывод из приложения без завершения - PullRequest
0 голосов
/ 02 марта 2020

У меня есть игра, в которой я запускаю скрипт оболочки. Когда игра запускается через терминал, она активно печатает информацию, такую ​​как «Подключено к серверу» или «Отключено» и т. Д.

const app = Application.currentApplication()
app.includeStandardAdditions = true

const terminalOutput = app.doShellScript('pathToGame');
console.log(terminalOutput);

Этот код распечатывается только тогда, когда приложение останавливается / выходит. Просто последнее утверждение напечатано. Я пытался найти способ напечатать каждое утверждение. Будь то в файле журнала или в качестве возвращаемого значения все, что он печатает во время выполнения процесса, без необходимости останавливать / выходить из него.

01:21:22: Application Running
01:21:23: Request connection to "ip address"
01:21:24: Connected to server "ip address"
01:45:01: Disconnected from server "ip address"
//Here my script would detect and try to log in again

Например: я открываю игру. Игра печатает «Запуск приложения», теперь с этим значением я знаю, что игра открыта, и я могу сказать своему сценарию войти в систему. Затем, если каким-то образом игра напечатает «Отключено от сервера», мое приложение обнаружит этот стандартный вывод и упадет. в функцию, в которой он попытается снова войти в систему.

Возможно ли получить стандартный вывод, пока приложение еще работает?

1 Ответ

0 голосов
/ 20 апреля 2020

Это невозможно при использовании простой JXA, так как doShellScript несколько ограничен.

Полное выполнение процесса все еще может быть достигнуто с использованием моста Objective- C. Ниже показано, как я выполняю команду в качестве подпроцесса в моем проекте , чтобы получить столбцы подключаемых терминалов.

// Import `Foundation` to be able use `NSTask`.
ObjC.import('Foundation');

// Launch `NSTask` `tput cols` to get number of cols.
const { pipe } = $.NSPipe;
const file = pipe.fileHandleForReading;
const task = $.NSTask.alloc.init;

task.launchPath = '/bin/sh';
task.arguments = ['-c', 'tput cols'];
task.standardOutput = pipe;

task.launch; // Run the task.

let data = file.readDataToEndOfFile; // Read the task's output.
file.closeFile;

// Parse the task's output.
data = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
const result = ObjC.unwrap(data); // Unwrap `NSString`.
return parseInt(result, 10);

Для вашего случая посмотрите https://developer.apple.com/documentation/foundation/pipe/1414352-filehandleforreading чтобы увидеть документацию о том, как получить данные от pipe.fileHandleForReading.

Ниже приведен пример моего решения, хотя оно еще не проверено.

// Import `Foundation` to be able use `NSTask`.
ObjC.import('Foundation');

// Launch `NSTask`.
const { pipe } = $.NSPipe;
const file = pipe.fileHandleForReading;
const task = $.NSTask.alloc.init;

task.launchPath = '/bin/sh';
task.arguments = ['-c', 'pathToYourGame'];
task.standardOutput = pipe;

task.launch; // Run the task.

let data;
for(;;) {
  data = file.availableData; // Read the task's output.
  if(!data) {
    file.closeFile;
    break;
  }

  // Parse the task's output.
  data = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
  const result = ObjC.unwrap(data);

  // Process your streaming data.
  doSomething(result);
}
...