NSTask没有从用户的环境中获取$ PATH

Abi*_*ern 13 bash shell cocoa objective-c nstask

我不知道为什么这个方法返回一个空字符串:

- (NSString *)installedGitLocation {
    NSString *launchPath = @"/usr/bin/which";

    // Set up the task
    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath:launchPath];
    NSArray *args = [NSArray arrayWithObject:@"git"];
    [task setArguments:args];

    // Set the output pipe.
    NSPipe *outPipe = [[NSPipe alloc] init];
    [task setStandardOutput:outPipe];

    [task launch];

    NSData *data = [[outPipe fileHandleForReading] readDataToEndOfFile];
    NSString *path = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    return path;
}
Run Code Online (Sandbox Code Playgroud)

如果不是@"git"作为参数传递,我传递@"which"/usr/bin/which按预期返回.所以至少原理是有效的.

从终端

$ which which
$ /usr/bin/which
$
$ which git
$ /usr/local/git/bin/git
Run Code Online (Sandbox Code Playgroud)

所以它在那里工作.

我唯一能想到的是which没有搜索我环境中的所有路径.

这真让我抓狂!有没有人有任何想法?

编辑: 看起来这是关于设置NSTask或用户的shell(例如,〜/ .bashrc),以便NSTask看到正确的环境($ PATH).

Vin*_*ble 21

尝试,

    [task setLaunchPath:@"/bin/bash"];
    NSArray *args = [NSArray arrayWithObjects:@"-l",
                     @"-c",
                     @"which git",
                     nil];
    [task setArguments: args];

这适用于Snow Leopard; 我没有在任何其他系统上测试过.-l(小写L)告诉bash"就好像它已被调用为登录shell",并且在此过程中它获取了我正常的$ PATH.如果启动路径设置为/ bit/sh,即使使用-l,这对我也无效.


Chr*_*son 13

通过NSTask运行任务使用fork()exec()实际运行任务.用户的交互式shell根本不涉及.由于$PATH(基本上)是一个shell概念,当你谈论以其他方式运行进程时,它不适用.

  • 但是如果用户在〜/ .MacOSX/environment.plist中设置PATH,则应用程序*会*接收PATH变量,子进程将继承它. (7认同)
  • 更重要的是,如果用户使用他的一个shell的运行命令文件设置了他的PATH,则应用程序不会接收该变量,因为它不是从shell运行的; 因此,子进程不会继承它,因为它是进程的直接子进程.(因为SO由于某种原因限制了长度) (2认同)