与 Console 和 Cocoa 不同的 $PATH?

Dr.*_*eon 3 macos bash cocoa objective-c environment-variables

好的,我一定遗漏了一些非常简单的东西,但这是:

  • 如果我echo $PATH在终端,我得到/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/drkameleon哪个是正确的

  • 现在,如果我运行 anNSTask并尝试执行一个简单的 bash 脚本 ( /usr/bin/env bash myscript.sh) 来 echo $PATH,它会打印/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin

(我什至尝试过getenv, 或打印整个[[NSProcessInfo processInfo] environment]字典,但PATH变量只是......错误)

这是怎么回事?我怎样才能访问终端中看到的真实内容 $PATH

小智 5

当通过 NSTask 执行命令时,不是你的 bash、zshell 或你正在使用的任何类型的 shell 被启动。因此,在终端中回显它们时,PATH(和其他环境变量)与您的环境变量不同。

原因: NSTask使用fork()exec()命令执行。

恕我直言,这个问题有两种可能的解决方案。

1.你可以通过setEnvironment:NSTask的方法设置想要的PATH

这是一些未经测试的示例代码,应该可以解决问题:

NSTask *task = //Configure your task
NSDictionary* env = [task environment];
NSString* currentPATH = env["PATH"];
NSString* yourPathExtension = @"/your/path";
env["PATH"] = (currentPATH != nil) ? [yourPath stringByAppendingFormat:@":%@", currentPATH] : yourPathExtension;
[task setEnvironment:env];
Run Code Online (Sandbox Code Playgroud)

这会:<old-PATH>在 NSTask 的当前 PATH 之后添加。

2. 你可以/bin/bash在 NSTask 中开始

task setLaunchPath:@"/bin/bash"];
NSArray *args = [NSArray arrayWithObjects:@"-l",
                 @"-c",
                 @"<your command here>",
                 nil];
[task setArguments: args];
Run Code Online (Sandbox Code Playgroud)

此任务将使用通过~/.bashrc等配置的 PATH 启动 /bin/bash 并在 bash 中执行命令。

优点:您的命令具有 bash 的所有常用环境变量

缺点:您依赖于用户 PATH 变量,该变量可能与您的完全不同,这可能会导致意外行为。

哪种解决方案最适合您取决于您​​的用例。在您提供的示例中,两种方法都应该可以正常工作。

一般来说,根据 NSTask 和 NSProcessInfo 文档,环境变量等于启动应用程序的进程的变量。因此,当您从 bash 启动应用程序时,您可能会解决您的问题。