Использование NSTask для запуска сценария оболочки, запускающего Node.JS

У меня есть приложение с какао, и я хочу запустить скрипт оболочки, который запускает Node.js. Я решил, что я сделаю это с NSTask

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/bash/start.sh"];
[task setArguments:[NSArray arrayWithObjects:@"start.sh", nil]];
[task setStandardOutput:[NSPipe pipe]];
[task setStandardInput:[NSPipe pipe]];

[task launch];

Скрипт находится в корне моего приложения. Я пробовал много вариантов в пути запуска, и я застрял. Любая помощь будет принята с благодарностью!

Редактировать:

Вот мой новый код, где я устанавливаю аргумент. Это все еще не будет работать по некоторым причинам.

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/bash"];
[task setArguments:[NSArray arrayWithObjects:[[NSBundle mainBundle] pathForResource:@"start" ofType:@"sh"], nil]];
[task launch];

3 ответа

Решение

Как вы уже догадались, проблема в вашем пути запуска.

Путь запуска должен быть одним путем к файлу. Имена файлов не будут работать *, и вы не можете назвать два отдельных файла по одному пути.

Ваш путь запуска должен быть полным абсолютным путем к bash. использование which bash в Терминале, чтобы узнать, какой это будет. (Это должно быть /bin/bash в стандартной установке OS X.)

Чтобы сказать bash запустить скрипт, вам нужно указать его в аргументах. Просто произнесение имени сценария не обрежет его; Вы должны указать полный абсолютный путь сценария. Нет никаких причин, чтобы имя скрипта было где-либо одним.

Я предполагаю, что скрипт является ресурсом в вашем комплекте приложений. Чтобы получить его абсолютный путь, спросите у вашего основного пакета URL-адрес этого ресурса, а затем получите путь к этому URL-адресу.

(Вы можете запросить путь к ресурсу напрямую, но работа с URL-адресами - это привычка, которую стоит выработать. Если вам нужно конкретное преимущество, метод на основе URL-адреса правильно называет свой второй аргумент расширением имени файла, а не "типом"; " тип "означает что-то другое в современном использовании.)


* Имена файлов обрабатываются как любые другие относительные пути. Относительные пути могут работать, но необходимо разрешить путь, который существует относительно текущего рабочего каталога. По умолчанию это / (корневой каталог), поэтому любой относительный путь, который будет работать, функционально эквивалентен абсолютному пути. Вы должны просто использовать абсолютные пути везде.

Вы должны попробовать это:

NSString *path = [[NSBundle mainBundle] pathForResource:@"SCRIPT_NAME" ofType:@"sh"];
NSString *commandToRun =[NSString stringWithFormat:@"/usr/bin/osascript -e\
                         'do shell script \"%@ args 2>&1 etc\" with administrator\
                         privileges'",path];
NSArray *arguments = [NSArray arrayWithObjects:
                      @"-c" ,
                      [NSString stringWithFormat:@"%@", commandToRun],
                      nil];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:arguments];

[task launch];
[task waitUntilExit];               // wait for completion
if ([task terminationStatus] != 0)  // check termination status
{
    NSLog(@"termination status is %d",[task terminationStatus]);

}

если TerminationStatus!= 0, существует проблема с задачей. что-то не так, вы должны проверить сценарий.

У меня была точно такая же проблема, и вот как я ее решил. Предполагая, что вы используете пакетное приложение, вы можете просто попросить NSBundle указать путь к исполняемому файлу приложения. Если ваш скрипт находится в той же директории, что и исполняемый файл (<name>.app/Contents/MacOS/), тогда это должно работать.

NSString *wd = [[NSBundle mainBundle] executablePath];
// this creates a path to <name.app>/Contents/MacOS/<name>/../script, where <name>
//    is the name of your app's executable file
NSString *path = @"/../script";
NSString *fullPath = [wd stringByAppendingString: path ];

[scriptTask setLaunchPath: fullPath];
[scriptTask launch];
Другие вопросы по тегам