【问题标题】:Using NSTask to launch shell script that launches Node.JS使用 NSTask 启动启动 Node.JS 的 shell 脚本
【发布时间】:2013-10-04 14:22:45
【问题描述】:

我有一个可可应用程序,我想启动一个 shell 脚本来启动 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];

【问题讨论】:

    标签: xcode node.js cocoa shell nstask


    【解决方案1】:

    如您所料,问题在于您的启动路径。

    启动路径必须是文件的单一路径。文件名不起作用*,您不能在同一路径中命名两个单独的文件。

    您的启动路径应该是 bash 的完整绝对路径。在终端中使用which bash 找出将是哪一个。 (它应该是 /bin/bash 在现有的 OS X 安装上。)

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

    我假设脚本是您的应用程序包中的资源。要获取其绝对路径,请向your main bundle 询问the URL to that resource,然后向get that URL's path 询问。

    (你可以直接要求a path for a resource,但是使用URLs是一个值得培养的习惯。如果你需要一个具体的优势,基于URL的方法正确地将它的第二个参数称为文件扩展名,而不是“类型”; “类型”在现代用法中意味着不同的东西。)


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

    【讨论】:

    • 我在设置参数和更改路径的地方编辑了我的答案。还是不行。
    • pathForResource: 是我认为错误的地方。该文档使我对如何获得正确的路径感到困惑。
    • @MinaDawoud:以什么方式?
    • 它谈到了 NSBundles 和 NSPaths,但没有将其链接回 NSTask。
    • @MinaDawoud:没有 NSPath;路径是 NSStrings。而且它没有引用 NSTask,因为获取路径是(或至少不是)特定于 NSTask 的……嗯,任务。 pathForResource:ofType:URLForResource:withExtension: 你如何在你的包中获得资源的路径;该路径适用于几乎所有直接使用,包括使用 NSTask 传递给任务。
    【解决方案2】:

    你应该试试这个:

    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 ,任务有问题。有问题,你应该检查脚本。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,这就是我解决它的方法。假设您使用的是捆绑应用程序,您只需向 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];
      

      【讨论】:

        猜你喜欢
        • 2017-04-07
        • 1970-01-01
        • 2014-03-11
        • 2015-08-11
        • 2011-10-09
        • 2011-11-26
        • 2013-01-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多