Использование 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];