0

I have a cocoa app and I want to launch a shell script that launches Node.js. I figured I would do that with 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];

The script is in the root of my application. I have tried many variations in the launch path and I am stuck. Any help would be greatly appreciated!

Edit:

Here is my new code where i set the argument. It still will not work for some reason.

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

3 回答 3

2

As you guessed, the problem is your launch path.

The launch path must be a single path to a file. Filenames won't work*, and you can't name two separate files in the same path.

Your launch path should be the complete absolute path to bash. Use which bash in the Terminal to find out which one that'll be. (It should be /bin/bash on a stock OS X install.)

To tell bash to run the script, you need to identify it in the arguments. Just saying the script's name won't cut it; you must give the script's complete absolute path. There's no reason to have the script's filename alone anywhere.

I assume the script is a resource in your application bundle. To get its absolute path, ask your main bundle for the URL to that resource, and then get that URL's path.

(You can ask for a path for a resource directly, but working with URLs is a habit worth developing. If you need a concrete advantage, the URL-based method correctly calls its second argument a filename extension, not a “type”; “type” means something different in modern usage.)


*Filenames are treated as any other relative paths. Relative paths can work, but need to resolve to a path that exists relative to the current working directory. By default, that's / (the root directory), so any relative path that would work is functionally equivalent to an absolute path. You should just use absolute paths everywhere.

于 2013-10-04T20:18:38.180 回答
1

你应该试试这个:

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]);

}

如果 terminateStatus != 0 ,任务有问题。有问题,你应该检查脚本。

于 2016-01-21T13:09:25.467 回答
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];
于 2014-11-20T21:25:21.617 回答