使用NSTask启动启动Node.JS的shell脚本

时间:2022-12-10 22:07:01

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

我有一个cocoa应用程序,我想启动一个启动Node.js的shell脚本。我想我会用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];

3 个解决方案

#1


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.)

您的启动路径应该是bash的完整绝对路径。在终端中使用哪个bash来找出哪个bash。 (它应该是/ bin / bash on 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.

要告诉bash运行脚本,您需要在参数中标识它。只是说剧本的名字不会削减它;你必须给出脚本完整的绝对路径。没有理由在任何地方单独使用脚本的文件名。

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.

我假设脚本是应用程序包中的资源。要获取其绝对路径,请向主捆绑包询问该资源的URL,然后获取该URL的路径。

(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.)

(您可以直接询问资源的路径,但使用URL是一种值得开发的习惯。如果您需要具体的优势,基于URL的方法正确地将其第二个参数称为文件扩展名,而不是“类型”;“类型“表示在现代使用中不同的东西。”


*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.

*文件名被视为任何其他相对路径。相对路径可以工作,但需要解析为相对于当前工作目录存在的路径。默认情况下,这是/(根目录),因此任何可用的相对路径在功能上等同于绝对路径。你应该在任何地方使用绝对路径。

#2


1  

you should try this:

你应该试试这个:

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

}

if the terminationStatus != 0 , there is a problem with task. something wrong, you should check the script.

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

#3


0  

I had this exact same problem, and this is how I solved it. Assuming you are using a bundle application, you can just ask NSBundle for the path to the application executable. If your script is in the same directory as the executable (<name>.app/Contents/MacOS/), then this should work.

我有同样的问题,这就是我解决它的方法。假设您正在使用捆绑应用程序,您可以向NSBundle询问应用程序可执行文件的路径。如果您的脚本与可执行文件位于同一目录中( .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];

#1


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.)

您的启动路径应该是bash的完整绝对路径。在终端中使用哪个bash来找出哪个bash。 (它应该是/ bin / bash on 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.

要告诉bash运行脚本,您需要在参数中标识它。只是说剧本的名字不会削减它;你必须给出脚本完整的绝对路径。没有理由在任何地方单独使用脚本的文件名。

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.

我假设脚本是应用程序包中的资源。要获取其绝对路径,请向主捆绑包询问该资源的URL,然后获取该URL的路径。

(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.)

(您可以直接询问资源的路径,但使用URL是一种值得开发的习惯。如果您需要具体的优势,基于URL的方法正确地将其第二个参数称为文件扩展名,而不是“类型”;“类型“表示在现代使用中不同的东西。”


*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.

*文件名被视为任何其他相对路径。相对路径可以工作,但需要解析为相对于当前工作目录存在的路径。默认情况下,这是/(根目录),因此任何可用的相对路径在功能上等同于绝对路径。你应该在任何地方使用绝对路径。

#2


1  

you should try this:

你应该试试这个:

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

}

if the terminationStatus != 0 , there is a problem with task. something wrong, you should check the script.

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

#3


0  

I had this exact same problem, and this is how I solved it. Assuming you are using a bundle application, you can just ask NSBundle for the path to the application executable. If your script is in the same directory as the executable (<name>.app/Contents/MacOS/), then this should work.

我有同样的问题,这就是我解决它的方法。假设您正在使用捆绑应用程序,您可以向NSBundle询问应用程序可执行文件的路径。如果您的脚本与可执行文件位于同一目录中( .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];